// 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 <ddk/debug.h>
#include <ddk/trace/event.h>
#include <fbl/auto_call.h>
#include <fbl/auto_lock.h>
#include <fuchsia/sysmem/c/fidl.h>
#include <lib/async/cpp/task.h>
#include <lib/edid/edid.h>
#include <lib/fidl/cpp/builder.h>
#include <lib/fidl/cpp/message.h>
#include <lib/image-format/image_format.h>
#include <math.h>
#include <utility>
#include <zircon/device/display-controller.h>
#include <zircon/pixelformat.h>

#include "client.h"

#define SELECT_TABLE_CASE(NAME) case NAME ## Ordinal: table = &NAME ## RequestTable; break
#define HANDLE_REQUEST_CASE(NAME)                                                                  \
    case fuchsia_hardware_display_Controller##NAME##Ordinal: {                                     \
        auto req = reinterpret_cast<const fuchsia_hardware_display_Controller##NAME##Request*>(    \
            msg.bytes().data());                                                                   \
        Handle##NAME(req, &builder, &out_type);                                                    \
        break;                                                                                     \
    }

namespace {

zx_status_t decode_message(fidl::Message* msg) {
    zx_status_t res;
    const fidl_type_t* table = nullptr;
    switch (msg->ordinal()) {
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerImportVmoImage);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerImportImage);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerReleaseImage);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerImportEvent);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerReleaseEvent);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerCreateLayer);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerDestroyLayer);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerSetDisplayMode);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerSetDisplayColorConversion);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerSetDisplayLayers);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerSetLayerPrimaryConfig);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerSetLayerPrimaryPosition);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerSetLayerPrimaryAlpha);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerSetLayerCursorConfig);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerSetLayerCursorPosition);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerSetLayerColorConfig);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerSetLayerImage);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerCheckConfig);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerApplyConfig);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerEnableVsync);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerSetVirtconMode);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerComputeLinearImageStride);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerAllocateVmo);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerImportBufferCollection);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerSetBufferCollectionConstraints);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerReleaseBufferCollection);
        SELECT_TABLE_CASE(fuchsia_hardware_display_ControllerGetSingleBufferFramebuffer);
    }
    if (table != nullptr) {
        const char* err;
        if ((res = msg->Decode(table, &err)) != ZX_OK) {
            zxlogf(INFO, "Error decoding message %d: %s\n", msg->ordinal(), err);
        }
    } else {
        zxlogf(INFO, "Unknown fidl ordinal %d\n", msg->ordinal());
        res = ZX_ERR_NOT_SUPPORTED;
    }
    return res;
}

bool frame_contains(const frame_t& a, const frame_t& b) {
    return b.x_pos < a.width
            && b.y_pos < a.height
            && b.x_pos + b.width <= a.width
            && b.y_pos + b.height <= a.height;
}

// We allocate some variable sized stack allocations based on the number of
// layers, so we limit the total number of layers to prevent blowing the stack.
static constexpr uint64_t kMaxLayers = 65536;

static constexpr uint32_t kInvalidLayerType = UINT32_MAX;

uint32_t calculate_refresh_rate_e2(const edid::timing_params_t params) {
    double total_pxls =
            (params.horizontal_addressable + params.horizontal_blanking) *
            (params.vertical_addressable + params.vertical_blanking);
    double pixel_clock_hz = params.pixel_freq_10khz * 1000 * 10;
    return static_cast<uint32_t>(round(100 * pixel_clock_hz / total_pxls));
}

// Removes and invokes EarlyRetire on all entries before end.
static void do_early_retire(list_node_t* list, display::image_node_t* end = nullptr) {
    display::image_node_t* node;
    while ((node = list_peek_head_type(list, display::image_node_t, link)) != end) {
        node->self->EarlyRetire();
        node->self.reset();
        list_remove_head(list);
    }
}

static void populate_image(const fuchsia_hardware_display_ImageConfig& image, image_t* image_out) {
    static_assert(offsetof(image_t, width) == offsetof(fuchsia_hardware_display_ImageConfig, width),
                  "Struct mismatch");
    static_assert(offsetof(image_t, height) ==
                      offsetof(fuchsia_hardware_display_ImageConfig, height),
                  "Struct mismatch");
    static_assert(offsetof(image_t, pixel_format) ==
                      offsetof(fuchsia_hardware_display_ImageConfig, pixel_format),
                  "Struct mismatch");
    static_assert(sizeof(image_plane_t) == sizeof(fuchsia_hardware_display_ImagePlane),
                  "Struct mismatch");
    static_assert(offsetof(image_t, type) == offsetof(fuchsia_hardware_display_ImageConfig, type),
                  "Struct mismatch");
    memcpy(image_out, &image, sizeof(fuchsia_hardware_display_ImageConfig));
}

static void populate_fidl_string(fidl_string_t* dest, fidl::Builder* dest_builder,
                                 const char* src, uint32_t n) {
    dest->data = reinterpret_cast<char*>(FIDL_ALLOC_PRESENT);
    dest->size = strnlen(src, n - 1) + 1;
    char* ptr = dest_builder->NewArray<char>(static_cast<uint32_t>(dest->size));
    snprintf(ptr, dest->size, "%s", src);
}

} // namespace

namespace display {

void Client::HandleControllerApi(async_dispatcher_t* dispatcher, async::WaitBase* self,
                                 zx_status_t status, const zx_packet_signal_t* signal) {
    if (status != ZX_OK) {
        zxlogf(INFO, "Unexpected status async status %d\n", status);
        ZX_DEBUG_ASSERT(false);
        return;
    } else if (signal->observed & ZX_CHANNEL_PEER_CLOSED) {
        zxlogf(TRACE, "Client closed\n");
        TearDown();
        return;
    }

    ZX_DEBUG_ASSERT(signal->observed & ZX_CHANNEL_READABLE);

    zx_handle_t in_handle;
    uint8_t in_byte_buffer[ZX_CHANNEL_MAX_MSG_BYTES];
    fidl::Message msg(fidl::BytePart(in_byte_buffer, ZX_CHANNEL_MAX_MSG_BYTES),
                      fidl::HandlePart(&in_handle, 1));
    status = msg.Read(server_handle_, 0);
    api_wait_.Begin(controller_->loop().dispatcher());

    if (status != ZX_OK) {
        zxlogf(TRACE, "Channel read failed %d\n", status);
        return;
    } else if ((status = decode_message(&msg)) != ZX_OK) {
        return;
    }

    uint8_t out_byte_buffer[ZX_CHANNEL_MAX_MSG_BYTES];
    fidl::Builder builder(out_byte_buffer, ZX_CHANNEL_MAX_MSG_BYTES);
    zx_handle_t out_handle = ZX_HANDLE_INVALID;
    bool has_out_handle = false;
    const fidl_type_t* out_type = nullptr;

    switch (msg.ordinal()) {
    HANDLE_REQUEST_CASE(ImportVmoImage);
    HANDLE_REQUEST_CASE(ImportImage);
    HANDLE_REQUEST_CASE(ReleaseImage);
    HANDLE_REQUEST_CASE(ImportEvent);
    HANDLE_REQUEST_CASE(ReleaseEvent);
    HANDLE_REQUEST_CASE(CreateLayer);
    HANDLE_REQUEST_CASE(DestroyLayer);
    HANDLE_REQUEST_CASE(SetDisplayMode);
    HANDLE_REQUEST_CASE(SetDisplayColorConversion);
    HANDLE_REQUEST_CASE(SetDisplayLayers);
    HANDLE_REQUEST_CASE(SetLayerPrimaryConfig);
    HANDLE_REQUEST_CASE(SetLayerPrimaryPosition);
    HANDLE_REQUEST_CASE(SetLayerPrimaryAlpha);
    HANDLE_REQUEST_CASE(SetLayerCursorConfig);
    HANDLE_REQUEST_CASE(SetLayerCursorPosition);
    HANDLE_REQUEST_CASE(SetLayerColorConfig);
    HANDLE_REQUEST_CASE(SetLayerImage);
    HANDLE_REQUEST_CASE(CheckConfig);
    HANDLE_REQUEST_CASE(ApplyConfig);
    HANDLE_REQUEST_CASE(EnableVsync);
    HANDLE_REQUEST_CASE(SetVirtconMode);
    HANDLE_REQUEST_CASE(ComputeLinearImageStride);
    HANDLE_REQUEST_CASE(ImportBufferCollection);
    HANDLE_REQUEST_CASE(ReleaseBufferCollection);
    HANDLE_REQUEST_CASE(SetBufferCollectionConstraints);
    case fuchsia_hardware_display_ControllerAllocateVmoOrdinal: {
        auto r = reinterpret_cast<const fuchsia_hardware_display_ControllerAllocateVmoRequest*>(
            msg.bytes().data());
        HandleAllocateVmo(r, &builder, &out_handle, &has_out_handle, &out_type);
        break;
    }
    case fuchsia_hardware_display_ControllerGetSingleBufferFramebufferOrdinal: {
        auto r = reinterpret_cast<
            const fuchsia_hardware_display_ControllerGetSingleBufferFramebufferRequest*>(
            msg.bytes().data());
        HandleGetSingleBufferFramebuffer(r, &builder, &out_handle, &has_out_handle, &out_type);
        break;
    }
    default:
        zxlogf(INFO, "Unknown ordinal %d\n", msg.ordinal());
    }

    fidl::BytePart resp_bytes = builder.Finalize();
    if (resp_bytes.actual() != 0) {
        ZX_DEBUG_ASSERT(out_type != nullptr);

        fidl::Message resp(std::move(resp_bytes),
                           fidl::HandlePart(&out_handle, 1, has_out_handle ? 1 : 0));
        resp.header() = msg.header();

        const char* err_msg;
        ZX_DEBUG_ASSERT_MSG(resp.Validate(out_type, &err_msg) == ZX_OK,
                            "Error validating fidl response \"%s\"\n", err_msg);
        if ((status = resp.Write(server_handle_, 0)) != ZX_OK) {
            zxlogf(ERROR, "Error writing response message %d\n", status);
        }
    }
}

void Client::HandleImportVmoImage(
    const fuchsia_hardware_display_ControllerImportVmoImageRequest* req,
    fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    auto resp = resp_builder->New<fuchsia_hardware_display_ControllerImportVmoImageResponse>();
    *resp_table = &fuchsia_hardware_display_ControllerImportVmoImageResponseTable;

    zx::vmo vmo(req->vmo);

    image_t dc_image;
    dc_image.height = req->image_config.height;
    dc_image.width = req->image_config.width;
    dc_image.pixel_format = req->image_config.pixel_format;
    dc_image.type = req->image_config.type;
    for (uint32_t i = 0; i < fbl::count_of(dc_image.planes); i++) {
        dc_image.planes[i].byte_offset = req->image_config.planes[i].byte_offset;
        dc_image.planes[i].bytes_per_row = req->image_config.planes[i].bytes_per_row;
    }

    zx::vmo dup_vmo;
    resp->res = vmo.duplicate(ZX_RIGHT_SAME_RIGHTS, &dup_vmo);
    if (resp->res == ZX_OK) {
        resp->res = controller_->dc()->ImportVmoImage(&dc_image, std::move(dup_vmo), req->offset);
    }

    if (resp->res == ZX_OK) {
        fbl::AllocChecker ac;
        uint32_t stride = 0;
        if (is_vc_) {
            stride = controller_->dc()->ComputeLinearStride(dc_image.width, dc_image.pixel_format);
        }
        auto image = fbl::AdoptRef(new (&ac) Image(controller_, dc_image, std::move(vmo), stride));
        if (!ac.check()) {
            controller_->dc()->ReleaseImage(&dc_image);

            resp->res = ZX_ERR_NO_MEMORY;
            return;
        }

        image->id = next_image_id_++;
        resp->image_id = image->id;
        images_.insert(std::move(image));
    }
}

void Client::HandleImportImage(const fuchsia_hardware_display_ControllerImportImageRequest* req,
                               fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    auto resp = resp_builder->New<fuchsia_hardware_display_ControllerImportImageResponse>();
    *resp_table = &fuchsia_hardware_display_ControllerImportImageResponseTable;

    auto it = collection_map_.find(req->collection_id);
    if (it == collection_map_.end()) {
        resp->res = ZX_ERR_INVALID_ARGS;
        return;
    }
    zx::channel& collection = it->second.driver;
    zx_status_t status2;
    zx_status_t status =
        fuchsia_sysmem_BufferCollectionCheckBuffersAllocated(collection.get(), &status2);

    if (status != ZX_OK || status2 != ZX_OK) {
        resp->res = ZX_ERR_SHOULD_WAIT;
        return;
    }

    image_t dc_image = {};
    dc_image.height = req->image_config.height;
    dc_image.width = req->image_config.width;
    dc_image.pixel_format = req->image_config.pixel_format;
    dc_image.type = req->image_config.type;

    resp->res = controller_->dc()->ImportImage(&dc_image, collection.get(), req->index);

    if (resp->res == ZX_OK) {
        auto release_image =
            fbl::MakeAutoCall([this, &dc_image]() { controller_->dc()->ReleaseImage(&dc_image); });
        zx::vmo vmo;
        uint32_t stride = 0;
        if (is_vc_) {
            ZX_ASSERT(it->second.kernel);
            fuchsia_sysmem_BufferCollectionInfo_2 info;
            zx_status_t status2;
            status = fuchsia_sysmem_BufferCollectionWaitForBuffersAllocated(it->second.kernel.get(),
                                                                            &status2, &info);
            if (status != ZX_OK || status2 != ZX_OK) {
                resp->res = ZX_ERR_NO_MEMORY;
                return;
            }
            fbl::Vector<zx::vmo> vmos;
            for (uint32_t i = 0; i < info.buffer_count; ++i) {
                vmos.push_back(zx::vmo(info.buffers[i].vmo));
            }

            if (!info.settings.has_image_format_constraints || req->index >= vmos.size()) {
                resp->res = ZX_ERR_OUT_OF_RANGE;
                return;
            }
            uint32_t minimum_row_bytes;
            if (!ImageFormatMinimumRowBytes(&info.settings.image_format_constraints, dc_image.width,
                                            &minimum_row_bytes)) {
                resp->res = ZX_ERR_INVALID_ARGS;
                return;
            }
            vmo = std::move(vmos[req->index]);
            stride = minimum_row_bytes / ZX_PIXEL_FORMAT_BYTES(dc_image.pixel_format);
        }

        fbl::AllocChecker ac;
        auto image = fbl::AdoptRef(new (&ac) Image(controller_, dc_image, std::move(vmo), stride));
        if (!ac.check()) {
            resp->res = ZX_ERR_NO_MEMORY;
            return;
        }

        image->id = next_image_id_++;
        resp->image_id = image->id;
        release_image.cancel();
        images_.insert(std::move(image));
    }
}

void Client::HandleReleaseImage(const fuchsia_hardware_display_ControllerReleaseImageRequest* req,
                                fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    auto image = images_.find(req->image_id);
    if (!image.IsValid()) {
        return;
    }

    if (CleanUpImage(&(*image))) {
        ApplyConfig();
    }
}

void Client::HandleImportEvent(const fuchsia_hardware_display_ControllerImportEventRequest* req,
                               fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    zx::event event(req->event);
    zx_status_t status = ZX_ERR_INVALID_ARGS;
    bool success = false;

    fbl::AutoLock lock(&fence_mtx_);

    // TODO(stevensd): it would be good for this not to be able to fail due to allocation failures
    if (req->id != INVALID_ID) {
        auto fence = fences_.find(req->id);
        if (!fence.IsValid()) {
            fbl::AllocChecker ac;
            auto new_fence = fbl::AdoptRef(new (&ac) Fence(this, controller_->loop().dispatcher(),
                                                           req->id, std::move(event)));
            if (ac.check() && new_fence->CreateRef()) {
                fences_.insert_or_find(std::move(new_fence));
                success = true;
            }
        } else {
            success = fence->CreateRef();
        }
    }

    if (!success) {
        zxlogf(ERROR, "Failed to import event#%ld (%d)\n", req->id, status);
        TearDown();
    }
}

void Client::HandleImportBufferCollection(
    const fuchsia_hardware_display_ControllerImportBufferCollectionRequest* req,
    fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    auto resp = resp_builder->New<fuchsia_hardware_display_ControllerImportBufferCollectionResponse>();
    *resp_table = &fuchsia_hardware_display_ControllerImportBufferCollectionResponseTable;
    zx::channel collection_token(req->collection_token);
    if (!sysmem_allocator_) {
        resp->res = ZX_ERR_INTERNAL;
        return;
    }

    // TODO: Switch to .contains() when C++20.
    if (collection_map_.count(req->collection_id)) {
        resp->res = ZX_ERR_INVALID_ARGS;
        return;
    }

    zx::channel vc_collection;

    // Make a second handle to represent the kernel's usage of the buffer as a
    // framebuffer, so we can set constraints and get VMOs for zx_framebuffer_set_range.
    if (is_vc_) {
        zx::channel vc_token_server, vc_token_client;
        zx::channel::create(0, &vc_token_server, &vc_token_client);
        zx_status_t status = fuchsia_sysmem_BufferCollectionTokenDuplicate(
            collection_token.get(), UINT32_MAX, vc_token_server.release());

        if (status != ZX_OK) {
            resp->res = ZX_ERR_INTERNAL;
            return;
        }
        status = fuchsia_sysmem_BufferCollectionTokenSync(collection_token.get());
        if (status != ZX_OK) {
            resp->res = ZX_ERR_INTERNAL;
            return;
        }

        zx::channel collection_server;
        zx::channel::create(0, &collection_server, &vc_collection);
        status = fuchsia_sysmem_AllocatorBindSharedCollection(
            sysmem_allocator_.get(), vc_token_client.release(), collection_server.release());

        if (status != ZX_OK) {
            resp->res = ZX_ERR_INTERNAL;
            return;
        }
    }

    zx::channel collection_server, collection_client;
    zx::channel::create(0, &collection_server, &collection_client);
    zx_status_t status = fuchsia_sysmem_AllocatorBindSharedCollection(
        sysmem_allocator_.get(), collection_token.release(), collection_server.release());

    if (status != ZX_OK) {
        resp->res = ZX_ERR_INTERNAL;
        return;
    }

    collection_map_[req->collection_id] =
        Collections{std::move(collection_client), std::move(vc_collection)};
    resp->res = ZX_OK;
}

void Client::HandleReleaseBufferCollection(
    const fuchsia_hardware_display_ControllerReleaseBufferCollectionRequest* req,
    fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    auto it = collection_map_.find(req->collection_id);
    if (it == collection_map_.end()) {
        return;
    }

    fuchsia_sysmem_BufferCollectionClose(it->second.driver.get());
    if (it->second.kernel) {
        fuchsia_sysmem_BufferCollectionClose(it->second.kernel.get());
    }
    collection_map_.erase(it);
}

void Client::HandleSetBufferCollectionConstraints(
    const fuchsia_hardware_display_ControllerSetBufferCollectionConstraintsRequest* req,
    fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    auto resp =
        resp_builder->New<fuchsia_hardware_display_ControllerSetBufferCollectionConstraintsResponse>();
    *resp_table = &fuchsia_hardware_display_ControllerSetBufferCollectionConstraintsResponseTable;
    auto it = collection_map_.find(req->collection_id);
    if (it == collection_map_.end()) {
        resp->res = ZX_ERR_INVALID_ARGS;
        return;
    }
    image_t dc_image;
    dc_image.height = req->config.height;
    dc_image.width = req->config.width;
    dc_image.pixel_format = req->config.pixel_format;
    dc_image.type = req->config.type;
    for (uint32_t i = 0; i < fbl::count_of(dc_image.planes); i++) {
        dc_image.planes[i].byte_offset = req->config.planes[i].byte_offset;
        dc_image.planes[i].bytes_per_row = req->config.planes[i].bytes_per_row;
    }

    resp->res =
        controller_->dc()->SetBufferCollectionConstraints(&dc_image, it->second.driver.get());

    if (resp->res == ZX_OK && is_vc_) {
        ZX_ASSERT(it->second.kernel);

        // Constraints to be used with zx_framebuffer_set_range.
        fuchsia_sysmem_BufferCollectionConstraints constraints = {};
        constraints.usage.display = fuchsia_sysmem_displayUsageLayer;
        constraints.has_buffer_memory_constraints = true;
        fuchsia_sysmem_BufferMemoryConstraints& buffer_constraints =
            constraints.buffer_memory_constraints;
        buffer_constraints.min_size_bytes = 0;
        buffer_constraints.max_size_bytes = 0xffffffff;
        buffer_constraints.physically_contiguous_required = true;
        buffer_constraints.secure_required = false;
        buffer_constraints.secure_permitted = false;
        constraints.image_format_constraints_count = 1;
        fuchsia_sysmem_ImageFormatConstraints& image_constraints =
            constraints.image_format_constraints[0];
        switch (req->config.pixel_format) {
        case ZX_PIXEL_FORMAT_RGB_x888:
        case ZX_PIXEL_FORMAT_ARGB_8888:
            image_constraints.pixel_format.type = fuchsia_sysmem_PixelFormatType_BGRA32;
            break;
        }

        image_constraints.color_spaces_count = 1;
        image_constraints.color_space[0].type = fuchsia_sysmem_ColorSpaceType_SRGB;
        image_constraints.min_coded_width = 0;
        image_constraints.max_coded_width = 0xffffffff;
        image_constraints.min_coded_height = 0;
        image_constraints.max_coded_height = 0xffffffff;
        image_constraints.min_bytes_per_row = 0;
        image_constraints.max_bytes_per_row = 0xffffffff;
        image_constraints.max_coded_width_times_coded_height = 0xffffffff;
        image_constraints.layers = 1;
        image_constraints.coded_width_divisor = 1;
        image_constraints.coded_height_divisor = 1;
        image_constraints.bytes_per_row_divisor = 4;
        image_constraints.start_offset_divisor = 1;
        image_constraints.display_width_divisor = 1;
        image_constraints.display_height_divisor = 1;

        if (image_constraints.pixel_format.type) {
            resp->res = fuchsia_sysmem_BufferCollectionSetConstraints(it->second.kernel.get(), true,
                                                                      &constraints);
        }
    }
}

void Client::HandleReleaseEvent(const fuchsia_hardware_display_ControllerReleaseEventRequest* req,
                                fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    // Hold a ref to prevent double locking if this destroys the fence.
    auto fence_ref = GetFence(req->id);
    if (fence_ref) {
        fbl::AutoLock lock(&fence_mtx_);
        fences_.find(req->id)->ClearRef();
    }
}

void Client::HandleCreateLayer(const fuchsia_hardware_display_ControllerCreateLayerRequest* req,
                               fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    auto resp = resp_builder->New<fuchsia_hardware_display_ControllerCreateLayerResponse>();
    *resp_table = &fuchsia_hardware_display_ControllerCreateLayerResponseTable;

    if (layers_.size() == kMaxLayers) {
        resp->res = ZX_ERR_NO_RESOURCES;
        return;
    }

    fbl::AllocChecker ac;
    auto new_layer = fbl::make_unique_checked<Layer>(&ac);
    if (!ac.check()) {
        resp->res = ZX_ERR_NO_MEMORY;
        return;
    }
    resp->layer_id = next_layer_id++;

    memset(&new_layer->pending_layer_, 0, sizeof(layer_t));
    memset(&new_layer->current_layer_, 0, sizeof(layer_t));
    new_layer->config_change_ = false;
    new_layer->pending_node_.layer = new_layer.get();
    new_layer->current_node_.layer = new_layer.get();
    new_layer->current_display_id_ = INVALID_DISPLAY_ID;
    new_layer->id = resp->layer_id;
    new_layer->current_layer_.type = kInvalidLayerType;
    new_layer->pending_layer_.type = kInvalidLayerType;

    layers_.insert(std::move(new_layer));

    resp->res = ZX_OK;
}

void Client::HandleDestroyLayer(const fuchsia_hardware_display_ControllerDestroyLayerRequest* req,
                                fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    auto layer = layers_.find(req->layer_id);
    if (!layer.IsValid()) {
        zxlogf(ERROR, "Tried to destroy invalid layer %ld\n", req->layer_id);
        TearDown();
        return;
    }
    if (layer->current_node_.InContainer() || layer->pending_node_.InContainer()) {
        zxlogf(ERROR, "Destroyed layer %ld which was in use\n", req->layer_id);
        TearDown();
        return;
    }

    auto destroyed = layers_.erase(req->layer_id);
    if (destroyed->pending_image_) {
        destroyed->pending_image_->DiscardAcquire();
    }
    do_early_retire(&destroyed->waiting_images_);
    if (destroyed->displayed_image_) {
        fbl::AutoLock lock(controller_->mtx());
        destroyed->displayed_image_->StartRetire();
    }
}

void Client::HandleSetDisplayMode(
    const fuchsia_hardware_display_ControllerSetDisplayModeRequest* req,
    fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    auto config = configs_.find(req->display_id);
    if (!config.IsValid()) {
        return;
    }

    fbl::AutoLock lock(controller_->mtx());
    const fbl::Vector<edid::timing_params_t>* edid_timings;
    const display_params_t* params;
    controller_->GetPanelConfig(req->display_id, &edid_timings, &params);

    if (edid_timings) {
        for (auto timing : *edid_timings) {
            if (timing.horizontal_addressable == req->mode.horizontal_resolution
                    && timing.vertical_addressable == req->mode.vertical_resolution
                    && timing.vertical_refresh_e2 == req->mode.refresh_rate_e2) {
                Controller::PopulateDisplayMode(timing, &config->pending_.mode);
                pending_config_valid_ = false;
                config->display_config_change_ = true;
                return;
            }
        }
        zxlogf(ERROR, "Invalid display mode\n");
    } else {
        zxlogf(ERROR, "Failed to find edid when setting display mode\n");
    }

    TearDown();
}

void Client::HandleSetDisplayColorConversion(
    const fuchsia_hardware_display_ControllerSetDisplayColorConversionRequest* req,
    fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    auto config = configs_.find(req->display_id);
    if (!config.IsValid()) {
        return;
    }

    config->pending_.cc_flags = 0;
    if (!isnan(req->preoffsets[0])) {
        config->pending_.cc_flags |= COLOR_CONVERSION_PREOFFSET;
        memcpy(config->pending_.cc_preoffsets, req->preoffsets, sizeof(req->preoffsets));
        static_assert(sizeof(req->preoffsets) == sizeof(config->pending_.cc_preoffsets), "");
    }

    if (!isnan(req->coefficients[0])) {
        config->pending_.cc_flags |= COLOR_CONVERSION_COEFFICIENTS;
        memcpy(config->pending_.cc_coefficients, req->coefficients, sizeof(req->coefficients));
        static_assert(sizeof(req->coefficients) == sizeof(config->pending_.cc_coefficients), "");
    }

    if (!isnan(req->postoffsets[0])) {
        config->pending_.cc_flags |= COLOR_CONVERSION_POSTOFFSET;
        memcpy(config->pending_.cc_postoffsets, req->postoffsets, sizeof(req->postoffsets));
        static_assert(sizeof(req->postoffsets) == sizeof(config->pending_.cc_postoffsets), "");
    }

    config->display_config_change_ = true;
    pending_config_valid_ = false;
}

void Client::HandleSetDisplayLayers(
    const fuchsia_hardware_display_ControllerSetDisplayLayersRequest* req,
    fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    auto config = configs_.find(req->display_id);
    if (!config.IsValid()) {
        return;
    }

    config->pending_layer_change_ = true;
    config->pending_layers_.clear();
    uint64_t* layer_ids = static_cast<uint64_t*>(req->layer_ids.data);
    for (uint64_t i = req->layer_ids.count - 1; i != UINT64_MAX; i--) {
        auto layer = layers_.find(layer_ids[i]);
        if (!layer.IsValid() || layer->pending_node_.InContainer()) {
            zxlogf(ERROR, "Tried to reuse an in-use layer\n");
            TearDown();
            return;
        }
        layer->pending_layer_.z_index = static_cast<uint32_t>(i);
        config->pending_layers_.push_front(&layer->pending_node_);
    }
    config->pending_.layer_count = static_cast<int32_t>(req->layer_ids.count);
    pending_config_valid_ = false;
}

void Client::HandleSetLayerPrimaryConfig(
    const fuchsia_hardware_display_ControllerSetLayerPrimaryConfigRequest* req,
    fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    auto layer = layers_.find(req->layer_id);
    if (!layer.IsValid()) {
        zxlogf(ERROR, "SetLayerPrimaryConfig on invalid layer\n");
        TearDown();
        return;
    }

    layer->pending_layer_.type = LAYER_TYPE_PRIMARY;
    primary_layer_t* primary_layer = &layer->pending_layer_.cfg.primary;

    populate_image(req->image_config, &primary_layer->image);

    // Initialize the src_frame and dest_frame with the default, full-image frame.
    frame_t new_frame = {
        .x_pos = 0, .y_pos = 0,
        .width = req->image_config.width, .height = req->image_config.height,
    };
    memcpy(&primary_layer->src_frame, &new_frame, sizeof(frame_t));
    memcpy(&primary_layer->dest_frame, &new_frame, sizeof(frame_t));

    primary_layer->transform_mode = FRAME_TRANSFORM_IDENTITY;

    layer->pending_image_config_gen_++;
    layer->pending_image_ = nullptr;
    layer->config_change_ = true;
    pending_config_valid_ = false;
}

void Client::HandleSetLayerPrimaryPosition(
    const fuchsia_hardware_display_ControllerSetLayerPrimaryPositionRequest* req,
    fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    auto layer = layers_.find(req->layer_id);
    if (!layer.IsValid() || layer->pending_layer_.type != LAYER_TYPE_PRIMARY) {
        zxlogf(ERROR, "SetLayerPrimaryPosition on invalid layer\n");
        TearDown();
        return;
    }
    if (req->transform > fuchsia_hardware_display_Transform_ROT_90_REFLECT_Y) {
        zxlogf(ERROR, "Invalid transform %d\n", req->transform);
        TearDown();
        return;
    }
    primary_layer_t* primary_layer = &layer->pending_layer_.cfg.primary;

    static_assert(sizeof(fuchsia_hardware_display_Frame) == sizeof(frame_t), "Struct mismatch");
    static_assert(offsetof(fuchsia_hardware_display_Frame, x_pos) == offsetof(frame_t, x_pos),
                  "Struct mismatch");
    static_assert(offsetof(fuchsia_hardware_display_Frame, y_pos) == offsetof(frame_t, y_pos),
                  "Struct mismatch");
    static_assert(offsetof(fuchsia_hardware_display_Frame, width) == offsetof(frame_t, width),
                  "Struct mismatch");
    static_assert(offsetof(fuchsia_hardware_display_Frame, height) == offsetof(frame_t, height),
                  "Struct mismatch");

    memcpy(&primary_layer->src_frame, &req->src_frame, sizeof(frame_t));
    memcpy(&primary_layer->dest_frame, &req->dest_frame, sizeof(frame_t));
    primary_layer->transform_mode = static_cast<uint8_t>(req->transform);

    layer->config_change_ = true;
    pending_config_valid_ = false;
}

void Client::HandleSetLayerPrimaryAlpha(
    const fuchsia_hardware_display_ControllerSetLayerPrimaryAlphaRequest* req,
    fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    auto layer = layers_.find(req->layer_id);
    if (!layer.IsValid() || layer->pending_layer_.type != LAYER_TYPE_PRIMARY) {
        zxlogf(ERROR, "SetLayerPrimaryAlpha on invalid layer\n");
        TearDown();
        return;
    }

    if (req->mode > fuchsia_hardware_display_AlphaMode_HW_MULTIPLY ||
        (!isnan(req->val) && (req->val < 0 || req->val > 1))) {
        zxlogf(ERROR, "Invalid args %d %f\n", req->mode, req->val);
        TearDown();
        return;
    }

    primary_layer_t* primary_layer = &layer->pending_layer_.cfg.primary;

    static_assert(fuchsia_hardware_display_AlphaMode_DISABLE == ALPHA_DISABLE, "Bad constant");
    static_assert(fuchsia_hardware_display_AlphaMode_PREMULTIPLIED == ALPHA_PREMULTIPLIED,
                  "Bad constant");
    static_assert(fuchsia_hardware_display_AlphaMode_HW_MULTIPLY == ALPHA_HW_MULTIPLY,
                  "Bad constant");

    primary_layer->alpha_mode = req->mode;
    primary_layer->alpha_layer_val = req->val;

    layer->config_change_ = true;
    pending_config_valid_ = false;
}

void Client::HandleSetLayerCursorConfig(
    const fuchsia_hardware_display_ControllerSetLayerCursorConfigRequest* req,
    fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    auto layer = layers_.find(req->layer_id);
    if (!layer.IsValid()) {
        zxlogf(ERROR, "SetLayerCursorConfig on invalid layer\n");
        TearDown();
        return;
    }

    layer->pending_layer_.type = LAYER_TYPE_CURSOR;
    layer->pending_cursor_x_ = layer->pending_cursor_y_ = 0;


    cursor_layer_t* cursor_layer = &layer->pending_layer_.cfg.cursor;
    populate_image(req->image_config, &cursor_layer->image);

    layer->pending_image_config_gen_++;
    layer->pending_image_ = nullptr;
    layer->config_change_ = true;
    pending_config_valid_ = false;
}

void Client::HandleSetLayerCursorPosition(
    const fuchsia_hardware_display_ControllerSetLayerCursorPositionRequest* req,
    fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    auto layer = layers_.find(req->layer_id);
    if (!layer.IsValid() || layer->pending_layer_.type != LAYER_TYPE_CURSOR) {
        zxlogf(ERROR, "SetLayerCursorPosition on invalid layer\n");
        TearDown();
        return;
    }

    layer->pending_cursor_x_ = req->x;
    layer->pending_cursor_y_ = req->y;

    layer->config_change_ = true;
}

void Client::HandleSetLayerColorConfig(
    const fuchsia_hardware_display_ControllerSetLayerColorConfigRequest* req,
    fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    auto layer = layers_.find(req->layer_id);
    if (!layer.IsValid()) {
        zxlogf(ERROR, "SetLayerColorConfig on invalid layer\n");
        return;
    }

    if (req->color_bytes.count != ZX_PIXEL_FORMAT_BYTES(req->pixel_format)) {
        zxlogf(ERROR, "SetLayerColorConfig with invalid color bytes\n");
        TearDown();
        return;
    }
    // Increase the size of the static array when large color formats are introduced
    ZX_ASSERT(req->color_bytes.count <= sizeof(layer->pending_color_bytes_));

    layer->pending_layer_.type = LAYER_TYPE_COLOR;
    color_layer_t* color_layer = &layer->pending_layer_.cfg.color;

    color_layer->format = req->pixel_format;
    memcpy(layer->pending_color_bytes_, req->color_bytes.data, sizeof(layer->pending_color_bytes_));

    layer->pending_image_ = nullptr;
    layer->config_change_ = true;
    pending_config_valid_ = false;
}

void Client::HandleSetLayerImage(const fuchsia_hardware_display_ControllerSetLayerImageRequest* req,
                                 fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    auto layer = layers_.find(req->layer_id);
    if (!layer.IsValid()) {
        zxlogf(ERROR, "SetLayerImage ordinal with invalid layer\n");
        TearDown();
        return;
    }
    if (layer->pending_layer_.type != LAYER_TYPE_PRIMARY &&
        layer->pending_layer_.type != LAYER_TYPE_CURSOR) {
        zxlogf(ERROR, "SetLayerImage ordinal with bad layer type\n");
        TearDown();
        return;
    }
    auto image = images_.find(req->image_id);
    if (!image.IsValid() || !image->Acquire()) {
        zxlogf(ERROR, "SetLayerImage ordinal with %s image\n", !image.IsValid() ? "invl" : "busy");
        TearDown();
        return;
    }
    image_t* cur_image = layer->pending_layer_.type == LAYER_TYPE_PRIMARY ?
            &layer->pending_layer_.cfg.primary.image : &layer->pending_layer_.cfg.cursor.image;
    if (!image->HasSameConfig(*cur_image)) {
        zxlogf(ERROR, "SetLayerImage with mismatch layer config\n");
        if (image.IsValid()) {
            image->DiscardAcquire();
        }
        TearDown();
        return;
    }

    if (layer->pending_image_) {
        layer->pending_image_->DiscardAcquire();
    }

    layer->pending_image_ = image.CopyPointer();
    layer->pending_wait_event_id_ = req->wait_event_id;
    layer->pending_signal_event_id_ = req->signal_event_id;
}

void Client::HandleCheckConfig(const fuchsia_hardware_display_ControllerCheckConfigRequest* req,
                               fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    *resp_table = &fuchsia_hardware_display_ControllerCheckConfigResponseTable;

    pending_config_valid_ = CheckConfig(resp_builder);

    if (req->discard) {
        // Go through layers and release any pending resources they claimed
        for (auto& layer : layers_) {
            layer.pending_image_config_gen_ = layer.current_image_config_gen_;
            if (layer.pending_image_) {
                layer.pending_image_->DiscardAcquire();
                layer.pending_image_ = nullptr;
            }
            if (layer.config_change_) {
                layer.pending_layer_ = layer.current_layer_;
                layer.config_change_ = false;

                layer.pending_cursor_x_ = layer.current_cursor_x_;
                layer.pending_cursor_y_ = layer.current_cursor_y_;
            }

            memcpy(layer.pending_color_bytes_,layer.current_color_bytes_,
                   sizeof(layer.pending_color_bytes_));
        }
        // Reset each config's pending layers to their current layers. Clear
        // all displays first in case layers were moved between displays.
        for (auto& config : configs_) {
            config.pending_layers_.clear();
        }
        for (auto& config : configs_) {
            fbl::SinglyLinkedList<layer_node_t*> current_layers;
            for (auto& layer_node : config.current_layers_) {
                current_layers.push_front(&layer_node.layer->pending_node_);
            }
            while (!current_layers.is_empty()) {
                auto layer = current_layers.pop_front();
                config.pending_layers_.push_front(layer);
            }
            config.pending_layer_change_ = false;

            config.pending_ = config.current_;
            config.display_config_change_ = false;
        }
        pending_config_valid_ = true;
    }
}

void Client::HandleApplyConfig(const fuchsia_hardware_display_ControllerApplyConfigRequest* req,
                               fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    if (!pending_config_valid_) {
        pending_config_valid_ = CheckConfig(nullptr);
        if (!pending_config_valid_) {
            zxlogf(INFO, "Tried to apply invalid config\n");
            return;
        }
    }

    // First go through and reset any current layer lists that are changing, so
    // we don't end up trying to put an image into two lists.
    for (auto& display_config : configs_) {
        if (display_config.pending_layer_change_) {
            while (!display_config.current_layers_.is_empty()) {
                display_config.current_layers_.pop_front();
            }
        }
    }

    for (auto& display_config : configs_) {
        if (display_config.display_config_change_) {
            display_config.current_ = display_config.pending_;
            display_config.display_config_change_ = false;
        }

        // Update any image layers. This needs to be done before migrating layers, as
        // that needs to know if there are any waiting images.
        for (auto layer_node : display_config.pending_layers_) {
            Layer* layer = layer_node.layer;
            // If the layer's image configuration changed, get rid of any current images
            if (layer->pending_image_config_gen_ != layer->current_image_config_gen_) {
                layer->current_image_config_gen_ = layer->pending_image_config_gen_;

                if (layer->pending_image_ == nullptr) {
                    zxlogf(ERROR, "Tried to apply configuration with missing image\n");
                    TearDown();
                    return;
                }

                while (!list_is_empty(&layer->waiting_images_)) {
                    do_early_retire(&layer->waiting_images_);
                }
                if (layer->displayed_image_ != nullptr) {
                    {
                        fbl::AutoLock lock(controller_->mtx());
                        layer->displayed_image_->StartRetire();
                    }
                    layer->displayed_image_ = nullptr;
                }
            }

            if (layer->pending_image_) {
                auto wait_fence = GetFence(layer->pending_wait_event_id_);
                if (wait_fence && wait_fence->InContainer()) {
                    zxlogf(ERROR, "Tried to wait with a busy event\n");
                    TearDown();
                    return;
                }
                layer_node.layer->pending_image_->PrepareFences(
                        std::move(wait_fence),
                        GetFence(layer->pending_signal_event_id_));
                {
                    fbl::AutoLock lock(controller_->mtx());
                    list_add_tail(&layer->waiting_images_, &layer->pending_image_->node.link);
                    layer->pending_image_->node.self = std::move(layer->pending_image_);
                }
            }
        }

        // If there was a layer change, update the current layers list.
        if (display_config.pending_layer_change_) {
            fbl::SinglyLinkedList<layer_node_t*> new_current;
            for (auto layer_node : display_config.pending_layers_) {
                new_current.push_front(&layer_node.layer->current_node_);
            }

            while (!new_current.is_empty()) {
                // Don't migrate images between displays if there are pending images. See
                // Controller::ApplyConfig for more details.
                auto* layer = new_current.pop_front();
                if (layer->layer->current_display_id_ != display_config.id
                        && layer->layer->displayed_image_
                        && !list_is_empty(&layer->layer->waiting_images_)) {
                    {
                        fbl::AutoLock lock(controller_->mtx());
                        layer->layer->displayed_image_->StartRetire();
                    }
                    layer->layer->displayed_image_ = nullptr;

                    // This doesn't need to be reset anywhere, since we really care about the last
                    // display this layer was shown on. Ignoring the 'null' display could cause
                    // unusual layer changes to trigger this unnecessary, but that's not wrong.
                    layer->layer->current_display_id_ = display_config.id;
                }
                layer->layer->current_layer_.z_index = layer->layer->pending_layer_.z_index;

                display_config.current_layers_.push_front(layer);
            }
            display_config.pending_layer_change_ = false;
            display_config.pending_apply_layer_change_ = true;
        }

        // Apply any pending configuration changes to active layers.
        for (auto layer_node : display_config.current_layers_) {
            Layer* layer = layer_node.layer;
            if (layer->config_change_) {
                layer->current_layer_ = layer->pending_layer_;
                layer->config_change_ = false;

                image_t* new_image_config = nullptr;
                if (layer->current_layer_.type == LAYER_TYPE_PRIMARY) {
                    new_image_config = &layer->current_layer_.cfg.primary.image;
                } else if (layer->current_layer_.type == LAYER_TYPE_CURSOR) {
                    new_image_config = &layer->current_layer_.cfg.cursor.image;

                    layer->current_cursor_x_ = layer->pending_cursor_x_;
                    layer->current_cursor_y_ = layer->pending_cursor_y_;

                    display_mode_t* mode = &display_config.current_.mode;
                    layer->current_layer_.cfg.cursor.x_pos =
                            fbl::clamp(layer->current_cursor_x_,
                                       -static_cast<int32_t>(new_image_config->width) + 1,
                                       static_cast<int32_t>(mode->h_addressable) - 1);
                    layer->current_layer_.cfg.cursor.y_pos =
                            fbl::clamp(layer->current_cursor_y_,
                                       -static_cast<int32_t>(new_image_config->height) + 1,
                                       static_cast<int32_t>(mode->v_addressable) - 1);
                } else if (layer->current_layer_.type == LAYER_TYPE_COLOR) {
                    memcpy(layer->current_color_bytes_, layer->pending_color_bytes_,
                           sizeof(layer->current_color_bytes_));
                    layer->current_layer_.cfg.color.color_list = layer->current_color_bytes_;
                    layer->current_layer_.cfg.color.color_count = 4;
                } else {
                    // type is validated in ::CheckConfig, so something must be very wrong.
                    ZX_ASSERT(false);
                }

                if (new_image_config && layer->displayed_image_) {
                    new_image_config->handle = layer->displayed_image_->info().handle;
                }
            }
        }
    }
    // Overflow doesn't matter, since stamps only need to be unique until
    // the configuration is applied with vsync.
    client_apply_count_++;

    ApplyConfig();
}

void Client::HandleEnableVsync(const fuchsia_hardware_display_ControllerEnableVsyncRequest* req,
                               fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    fbl::AutoLock lock(controller_->mtx());
    proxy_->EnableVsync(req->enable);
}

void Client::HandleSetVirtconMode(
    const fuchsia_hardware_display_ControllerSetVirtconModeRequest* req,
    fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    if (!is_vc_) {
        zxlogf(ERROR, "Illegal non-virtcon ownership\n");
        TearDown();
        return;
    }
    controller_->SetVcMode(req->mode);
}

void Client::HandleComputeLinearImageStride(
    const fuchsia_hardware_display_ControllerComputeLinearImageStrideRequest* req,
    fidl::Builder* resp_builder, const fidl_type_t** resp_table) {
    auto resp =
        resp_builder->New<fuchsia_hardware_display_ControllerComputeLinearImageStrideResponse>();
    *resp_table = &fuchsia_hardware_display_ControllerComputeLinearImageStrideResponseTable;
    resp->stride = controller_->dc()->ComputeLinearStride(req->width, req->pixel_format);
}

void Client::HandleAllocateVmo(const fuchsia_hardware_display_ControllerAllocateVmoRequest* req,
                               fidl::Builder* resp_builder, zx_handle_t* handle_out,
                               bool* has_handle_out, const fidl_type_t** resp_table) {
    auto resp = resp_builder->New<fuchsia_hardware_display_ControllerAllocateVmoResponse>();
    *resp_table = &fuchsia_hardware_display_ControllerAllocateVmoResponseTable;

    zx::vmo vmo;
    resp->res = controller_->dc()->AllocateVmo(req->size, &vmo);
    *has_handle_out = resp->res == ZX_OK;
    *handle_out = vmo.release();
    resp->vmo = *has_handle_out ? FIDL_HANDLE_PRESENT : FIDL_HANDLE_ABSENT;
}

void Client::HandleGetSingleBufferFramebuffer(
    const fuchsia_hardware_display_ControllerGetSingleBufferFramebufferRequest* req,
    fidl::Builder* resp_builder, zx_handle_t* handle_out, bool* has_handle_out,
    const fidl_type_t** resp_table) {
    auto resp =
        resp_builder->New<fuchsia_hardware_display_ControllerGetSingleBufferFramebufferResponse>();
    *resp_table = &fuchsia_hardware_display_ControllerGetSingleBufferFramebufferResponseTable;

    zx::vmo vmo;
    uint32_t stride = 0;
    resp->res = controller_->dc()->GetSingleBufferFramebuffer(&vmo, &stride);
    *has_handle_out = resp->res == ZX_OK;
    *handle_out = vmo.release();
    resp->vmo = *has_handle_out ? FIDL_HANDLE_PRESENT : FIDL_HANDLE_ABSENT;
    resp->stride = stride;
}

bool Client::CheckConfig(fidl::Builder* resp_builder) {
    const display_config_t* configs[configs_.size()];
    layer_t* layers[layers_.size()];
    uint32_t layer_cfg_results[layers_.size()];
    uint32_t* display_layer_cfg_results[configs_.size()];
    memset(layer_cfg_results, 0, layers_.size() * sizeof(uint32_t));

    fuchsia_hardware_display_ControllerCheckConfigResponse* resp = nullptr;
    if (resp_builder) {
        resp = resp_builder->New<fuchsia_hardware_display_ControllerCheckConfigResponse>();
        resp->res = fuchsia_hardware_display_ConfigResult_OK;
        resp->ops.count = 0;
        resp->ops.data = reinterpret_cast<void*>(FIDL_ALLOC_PRESENT);
    }

    bool config_fail = false;
    int config_idx = 0;
    int layer_idx = 0;
    for (auto& display_config : configs_) {
        if (display_config.pending_layers_.is_empty()) {
            continue;
        }

        // Put this display's display_config_t* into the compact array
        configs[config_idx] = &display_config.pending_;

        // Set the index in the primary result array with this display's layer result array
        display_layer_cfg_results[config_idx++] = layer_cfg_results + layer_idx;

        // Create this display's compact layer_t* array
        display_config.pending_.layer_list = layers + layer_idx;

        // Frame used for checking that each layer's dest_frame lies entirely
        // within the composed output.
        frame_t display_frame = {
            .x_pos = 0, .y_pos = 0,
            .width = display_config.pending_.mode.h_addressable,
            .height = display_config.pending_.mode.v_addressable,
        };

        // Do any work that needs to be done to make sure that the pending layer_t structs
        // are up to date, and validate that the configuration doesn't violate any API
        // constraints.
        for (auto& layer_node : display_config.pending_layers_) {
            layers[layer_idx++] = &layer_node.layer->pending_layer_;

            bool invalid = false;
            if (layer_node.layer->pending_layer_.type == LAYER_TYPE_PRIMARY) {
                primary_layer_t* layer = &layer_node.layer->pending_layer_.cfg.primary;
                // Frame for checking that the layer's src_frame lies entirely
                // within the source image.
                frame_t image_frame = {
                    .x_pos = 0, .y_pos = 0,
                    .width = layer->image.width, .height = layer->image.height,
                };
                invalid = (!frame_contains(image_frame, layer->src_frame)
                        || !frame_contains(display_frame, layer->dest_frame));

                if (!invalid) {
                    invalid = true;
                    for (auto fmt : display_config.pixel_formats_) {
                        if (fmt == layer->image.pixel_format) {
                            invalid = false;
                            break;
                        }
                    }
                }
            } else if (layer_node.layer->pending_layer_.type == LAYER_TYPE_CURSOR) {
                invalid = true;
                auto& cursor_cfg = layer_node.layer->pending_layer_.cfg.cursor;
                for (auto& cursor_info : display_config.cursor_infos_) {
                    if (cursor_info.format == cursor_cfg.image.pixel_format) {
                        invalid = false;
                        break;
                    }
                }
            } else if (layer_node.layer->pending_layer_.type == LAYER_TYPE_COLOR) {
                // There aren't any API constraints on valid colors.
                layer_node.layer->pending_layer_.cfg.color.color_list =
                        layer_node.layer->pending_color_bytes_;
                layer_node.layer->pending_layer_.cfg.color.color_count = 4;
            } else {
                invalid = true;
            }

            if (invalid) {
                // Continue to the next display, since there's nothing more to check for this one.
                config_fail = true;
                break;
            }
        }
    }

    if (config_fail) {
        if (resp) {
            resp->res = fuchsia_hardware_display_ConfigResult_INVALID_CONFIG;
        }
        // If the config is invalid, there's no point in sending it to the impl driver.
        return false;
    }

    size_t layer_cfg_results_count;
    uint32_t display_cfg_result =
        controller_->dc()->CheckConfiguration(configs, config_idx, display_layer_cfg_results,
                                              &layer_cfg_results_count);

    if (display_cfg_result != CONFIG_DISPLAY_OK) {
        if (resp) {
            resp->res = display_cfg_result == CONFIG_DISPLAY_TOO_MANY
                            ? fuchsia_hardware_display_ConfigResult_TOO_MANY_DISPLAYS
                            : fuchsia_hardware_display_ConfigResult_UNSUPPORTED_DISPLAY_MODES;
        }
        return false;
    }

    bool layer_fail = false;
    for (int i = 0; i < config_idx && !layer_fail; i++) {
        for (unsigned j = 0; j < configs[i]->layer_count && !layer_fail; j++) {
            if (display_layer_cfg_results[i][j]) {
                layer_fail = true;
            }
        }
    }

    // Return unless we need to finish constructing the response
    if (!layer_fail) {
        return true;
    } else if (!resp_builder) {
        return false;
    }
    resp->res = fuchsia_hardware_display_ConfigResult_UNSUPPORTED_CONFIG;

    static_assert((1 << fuchsia_hardware_display_ClientCompositionOpcode_CLIENT_USE_PRIMARY) ==
                      CLIENT_USE_PRIMARY,
                  "Const mismatch");
    static_assert((1 << fuchsia_hardware_display_ClientCompositionOpcode_CLIENT_MERGE_BASE) ==
                      CLIENT_MERGE_BASE,
                  "Const mismatch");
    static_assert((1 << fuchsia_hardware_display_ClientCompositionOpcode_CLIENT_MERGE_SRC) ==
                      CLIENT_MERGE_SRC,
                  "Const mismatch");
    static_assert((1 << fuchsia_hardware_display_ClientCompositionOpcode_CLIENT_FRAME_SCALE) ==
                      CLIENT_FRAME_SCALE,
                  "Const mismatch");
    static_assert((1 << fuchsia_hardware_display_ClientCompositionOpcode_CLIENT_SRC_FRAME) ==
                      CLIENT_SRC_FRAME,
                  "Const mismatch");
    static_assert((1 << fuchsia_hardware_display_ClientCompositionOpcode_CLIENT_TRANSFORM) ==
                      CLIENT_TRANSFORM,
                  "Const mismatch");
    static_assert((1 << fuchsia_hardware_display_ClientCompositionOpcode_CLIENT_COLOR_CONVERSION) ==
                      CLIENT_COLOR_CONVERSION,
                  "Const mismatch");
    static_assert((1 << fuchsia_hardware_display_ClientCompositionOpcode_CLIENT_ALPHA) ==
                      CLIENT_ALPHA,
                  "Const mismatch");
    constexpr uint32_t kAllErrors = (CLIENT_ALPHA << 1) - 1;


    layer_idx = 0;
    for (auto& display_config : configs_) {
        if (display_config.pending_layers_.is_empty()) {
            continue;
        }

        bool seen_base = false;
        for (auto& layer_node : display_config.pending_layers_) {
            uint32_t err = kAllErrors & layer_cfg_results[layer_idx];
            // Fixup the error flags if the driver impl incorrectly set multiple MERGE_BASEs
            if (err & CLIENT_MERGE_BASE) {
                if (seen_base) {
                    err &= ~CLIENT_MERGE_BASE;
                    err |= CLIENT_MERGE_SRC;
                } else {
                    seen_base = true;
                    err &= ~CLIENT_MERGE_SRC;
                }
            }

            for (uint8_t i = 0; i < 32; i++) {
                if (err & (1 << i)) {
                    auto op = resp_builder->New<fuchsia_hardware_display_ClientCompositionOp>();
                    op->display_id = display_config.id;
                    op->layer_id = layer_node.layer->id;
                    op->opcode = i;
                    resp->ops.count++;
                }
            }
            layer_idx++;
        }
    }
    return false;
}

void Client::ApplyConfig() {
    ZX_DEBUG_ASSERT(controller_->current_thread_is_loop());
    TRACE_DURATION("gfx", "Display::Client::ApplyConfig");

    bool config_missing_image = false;
    layer_t* layers[layers_.size()];
    int layer_idx = 0;
    for (auto& display_config : configs_) {
        display_config.current_.layer_count = 0;
        display_config.current_.layer_list = layers + layer_idx;
        display_config.vsync_layer_count_ = 0;

        // Displays with no current layers are filtered out in Controller::ApplyConfig,
        // after it updates its own image tracking logic.

        for (auto layer_node : display_config.current_layers_) {
            // Find the newest image which has become ready
            Layer* layer = layer_node.layer;
            image_node_t* node = list_peek_tail_type(&layer->waiting_images_, image_node_t, link);
            while (node != nullptr && !node->self->IsReady()) {
                node = list_prev_type(&layer->waiting_images_, &node->link, image_node_t, link);
            }
            if (node != nullptr) {
                if (layer->displayed_image_ != nullptr) {
                    // Start retiring the image which had been displayed
                    fbl::AutoLock lock(controller_->mtx());
                    layer->displayed_image_->StartRetire();
                } else {
                    // Turning on a new layer is a (pseudo) layer change
                    display_config.pending_apply_layer_change_ = true;
                }

                // Drop any images older than node.
                do_early_retire(&layer->waiting_images_, node);

                layer->displayed_image_ = std::move(node->self);
                list_remove_head(&layer->waiting_images_);

                uint64_t handle = layer->displayed_image_->info().handle;
                if (layer->current_layer_.type == LAYER_TYPE_PRIMARY) {
                    layer->current_layer_.cfg.primary.image.handle = handle;
                } else if (layer->current_layer_.type == LAYER_TYPE_CURSOR) {
                    layer->current_layer_.cfg.cursor.image.handle = handle;
                } else {
                    // type is validated in ::CheckConfig, so something must be very wrong.
                    ZX_ASSERT(false);
                }
            }

            if (is_vc_) {
                if (layer->displayed_image_) {
                    // If the virtcon is displaying an image, set it as the kernel's framebuffer
                    // vmo. If the virtcon is displaying images on multiple displays, this ends
                    // executing multiple times, but the extra work is okay since the virtcon
                    // shouldn't be flipping images.
                    console_fb_display_id_ = display_config.id;

                    auto fb = layer->displayed_image_;
                    uint32_t stride = fb->stride_px();
                    uint32_t size = fb->info().height *
                            ZX_PIXEL_FORMAT_BYTES(fb->info().pixel_format) * stride;
                    // Please do not use get_root_resource() in new code. See ZX-1497.
                    zx_framebuffer_set_range(get_root_resource(),
                                       fb->vmo().get(), size, fb->info().pixel_format,
                                       fb->info().width, fb->info().height, stride);
                } else if (console_fb_display_id_ == display_config.id) {
                    // If this display doesnt' have an image but it was the display which had the
                    // kernel's framebuffer, make the kernel drop the reference. Note that this
                    // executes when tearing down the virtcon client.
                    // Please do not use get_root_resource() in new code. See ZX-1497.
                    zx_framebuffer_set_range(get_root_resource(), ZX_HANDLE_INVALID, 0, 0, 0, 0, 0);
                    console_fb_display_id_ = -1;
                }
            }

            display_config.current_.layer_count++;
            layers[layer_idx++] = &layer->current_layer_;
            if (layer->current_layer_.type != LAYER_TYPE_COLOR) {
                display_config.vsync_layer_count_++;
                if (layer->displayed_image_ == nullptr) {
                    config_missing_image = true;
                }
            }
        }
    }

    if (!config_missing_image && is_owner_) {
        DisplayConfig* dc_configs[configs_.size()];
        int dc_idx = 0;
        for (auto& c : configs_) {
            dc_configs[dc_idx++] = &c;
        }
        controller_->ApplyConfig(dc_configs, dc_idx, is_vc_, client_apply_count_);
    }
}

void Client::SetOwnership(bool is_owner) {
    ZX_DEBUG_ASSERT(controller_->current_thread_is_loop());

    is_owner_ = is_owner;

    fuchsia_hardware_display_ControllerClientOwnershipChangeEvent msg = {};
    msg.hdr.ordinal = fuchsia_hardware_display_ControllerClientOwnershipChangeOrdinal;
    msg.has_ownership = is_owner;

    zx_status_t status = zx_channel_write(server_handle_, 0, &msg, sizeof(msg), nullptr, 0);
    if (status != ZX_OK) {
        zxlogf(ERROR, "Error writing remove message %d\n", status);
    }

    ApplyConfig();
}

void Client::OnDisplaysChanged(const uint64_t* displays_added, size_t added_count,
                               const uint64_t* displays_removed, size_t removed_count) {
    ZX_DEBUG_ASSERT(controller_->current_thread_is_loop());
    ZX_DEBUG_ASSERT(mtx_trylock(controller_->mtx()) == thrd_busy);

    uint8_t bytes[ZX_CHANNEL_MAX_MSG_BYTES];
    fidl::Builder builder(bytes, ZX_CHANNEL_MAX_MSG_BYTES);
    auto req = builder.New<fuchsia_hardware_display_ControllerDisplaysChangedEvent>();
    zx_status_t status;
    req->hdr = {};
    req->hdr.ordinal = fuchsia_hardware_display_ControllerDisplaysChangedOrdinal;
    req->added.count = 0;
    req->added.data = reinterpret_cast<void*>(FIDL_ALLOC_PRESENT);
    req->removed.count = 0;
    req->removed.data = reinterpret_cast<void*>(FIDL_ALLOC_PRESENT);

    for (unsigned i = 0; i < removed_count; i++) {
        // TODO(stevensd): Delayed removal can cause conflicts if the driver reuses
        // display ids. Move display id generation into the core driver.
        if (configs_.find(displays_removed[i]).IsValid()) {
            req->removed.count++;
        }
    }

    for (unsigned i = 0; i < added_count; i++) {
        fbl::AllocChecker ac;
        auto config = fbl::make_unique_checked<DisplayConfig>(&ac);
        if (!ac.check()) {
            zxlogf(WARN, "Out of memory when processing hotplug\n");
            continue;
        }

        config->id = displays_added[i];

        if (!controller_->GetSupportedPixelFormats(config->id,
                                                   &config->pixel_formats_)) {
            zxlogf(WARN, "Failed to get pixel formats when processing hotplug\n");
            continue;
        }

        if (!controller_->GetCursorInfo(config->id, &config->cursor_infos_)) {
            zxlogf(WARN, "Failed to get cursor info when processing hotplug\n");
            continue;
        }

        const fbl::Vector<edid::timing_params_t>* edid_timings;
        const display_params_t* params;
        if (!controller_->GetPanelConfig(config->id, &edid_timings, &params)) {
            // This can only happen if the display was already disconnected.
            zxlogf(WARN, "No config when adding display\n");
            continue;
        }
        req->added.count++;

        config->current_.display_id = config->id;
        config->current_.layer_list = nullptr;
        config->current_.layer_count = 0;

        if (edid_timings) {
            Controller::PopulateDisplayMode((*edid_timings)[0], &config->current_.mode);
        } else {
            config->current_.mode = {};
            config->current_.mode.h_addressable = params->width;
            config->current_.mode.v_addressable = params->height;
        }

        config->current_.cc_flags = 0;

        config->pending_ = config->current_;

        configs_.insert(std::move(config));
    }

    // We need 2 loops, since we need to make sure we allocate the
    // correct size array in the fidl response.
    fuchsia_hardware_display_Info* coded_configs = nullptr;
    if (req->added.count > 0) {
        coded_configs = builder.NewArray<fuchsia_hardware_display_Info>(
            static_cast<uint32_t>(req->added.count));
    }

    for (unsigned i = 0; i < added_count; i++) {
        auto config = configs_.find(displays_added[i]);
        if (!config.IsValid()) {
            continue;
        }

        const fbl::Vector<edid::timing_params>* edid_timings;
        const display_params_t* params;
        controller_->GetPanelConfig(config->id, &edid_timings, &params);

        coded_configs[i].id = config->id;
        coded_configs[i].pixel_format.data = reinterpret_cast<void*>(FIDL_ALLOC_PRESENT);
        coded_configs[i].modes.data = reinterpret_cast<void*>(FIDL_ALLOC_PRESENT);
        coded_configs[i].cursor_configs.data = reinterpret_cast<void*>(FIDL_ALLOC_PRESENT);

        if (edid_timings) {
            coded_configs[i].modes.count = edid_timings->size();
            for (auto timing : *edid_timings) {
                auto mode = builder.New<fuchsia_hardware_display_Mode>();

                mode->horizontal_resolution = timing.horizontal_addressable;
                mode->vertical_resolution = timing.vertical_addressable;
                mode->refresh_rate_e2 = timing.vertical_refresh_e2;
            }
        } else {
            coded_configs[i].modes.count = 1;
            auto mode = builder.New<fuchsia_hardware_display_Mode>();
            mode->horizontal_resolution = params->width;
            mode->vertical_resolution = params->height;
            mode->refresh_rate_e2 = params->refresh_rate_e2;
        }

        static_assert(sizeof(zx_pixel_format_t) == sizeof(int32_t), "Bad pixel format size");
        coded_configs[i].pixel_format.count = config->pixel_formats_.size();
        memcpy(builder.NewArray<zx_pixel_format_t>(
                        static_cast<uint32_t>(config->pixel_formats_.size())),
               config->pixel_formats_.get(),
               sizeof(zx_pixel_format_t) * config->pixel_formats_.size());

        static_assert(offsetof(cursor_info_t, width) ==
                          offsetof(fuchsia_hardware_display_CursorInfo, width),
                      "Bad struct");
        static_assert(offsetof(cursor_info_t, height) ==
                          offsetof(fuchsia_hardware_display_CursorInfo, height),
                      "Bad struct");
        static_assert(offsetof(cursor_info_t, format) ==
                          offsetof(fuchsia_hardware_display_CursorInfo, pixel_format),
                      "Bad struct");
        static_assert(sizeof(cursor_info_t) <= sizeof(fuchsia_hardware_display_CursorInfo),
                      "Bad size");
        coded_configs[i].cursor_configs.count = config->cursor_infos_.size();
        auto coded_cursor_configs = builder.NewArray<fuchsia_hardware_display_CursorInfo>(
            static_cast<uint32_t>(config->cursor_infos_.size()));
        for (unsigned i = 0; i < config->cursor_infos_.size(); i++) {
            memcpy(&coded_cursor_configs[i], &config->cursor_infos_[i], sizeof(cursor_info_t));
        }

        const char* manufacturer_name = "";
        const char* monitor_name = "";
        const char* monitor_serial = "";
        if (!controller_->GetDisplayIdentifiers(displays_added[i], &manufacturer_name,
                                                &monitor_name, &monitor_serial)) {
            zxlogf(ERROR, "Failed to get display identifiers\n");
            ZX_DEBUG_ASSERT(false);
        }

        populate_fidl_string(&coded_configs[i].manufacturer_name, &builder, manufacturer_name,
                             fuchsia_hardware_display_identifierMaxLen);
        populate_fidl_string(&coded_configs[i].monitor_name, &builder, monitor_name,
                             fuchsia_hardware_display_identifierMaxLen);
        populate_fidl_string(&coded_configs[i].monitor_serial, &builder, monitor_serial,
                             fuchsia_hardware_display_identifierMaxLen);
    }

    if (req->removed.count > 0) {
        auto removed_ids = builder.NewArray<uint64_t>(static_cast<uint32_t>(req->removed.count));
        uint32_t idx = 0;
        for (unsigned i = 0; i < removed_count; i++) {
            auto display = configs_.erase(displays_removed[i]);
            if (display) {
                display->pending_layers_.clear();
                display->current_layers_.clear();
                removed_ids[idx++] = display->id;
            }
        }
    }

    if (req->added.count > 0 || req->removed.count > 0) {
        fidl::Message msg(builder.Finalize(), fidl::HandlePart());
        const char* err;
        ZX_DEBUG_ASSERT_MSG(
            msg.Validate(&fuchsia_hardware_display_ControllerDisplaysChangedEventTable, &err) ==
                ZX_OK,
            "Failed to validate \"%s\"", err);

        if ((status = msg.Write(server_handle_, 0)) != ZX_OK) {
            zxlogf(ERROR, "Error writing remove message %d\n", status);
        }
    }
}

fbl::RefPtr<FenceReference> Client::GetFence(uint64_t id) {
    if (id == INVALID_ID) {
        return nullptr;
    }
    fbl::AutoLock lock(&fence_mtx_);
    auto fence = fences_.find(id);
    return fence.IsValid() ? fence->GetReference() : nullptr;
}

void Client::OnFenceFired(FenceReference* fence) {
    for (auto& layer: layers_) {
        image_node_t* waiting;
        list_for_every_entry(&layer.waiting_images_, waiting, image_node_t, link) {
            waiting->self->OnFenceReady(fence);
        }
    }
    ApplyConfig();
}

void Client::OnRefForFenceDead(Fence* fence) {
    fbl::AutoLock lock(&fence_mtx_);
    if (fence->OnRefDead()) {
        fences_.erase(fence->id);
    }
}

void Client::TearDown() {
    ZX_DEBUG_ASSERT(controller_->loop().GetState() == ASYNC_LOOP_SHUTDOWN
            || controller_->current_thread_is_loop());
    pending_config_valid_ = false;

    // Teardown stops events from the channel, but not from the ddk, so we
    // need to make sure we don't try to teardown multiple times.
    if (!IsValid()) {
        return;
    }

    if (api_wait_.object() != ZX_HANDLE_INVALID) {
        api_wait_.Cancel();
        api_wait_.set_object(ZX_HANDLE_INVALID);
    }
    server_handle_ = ZX_HANDLE_INVALID;

    CleanUpImage(nullptr);

    // Use a temporary list to prevent double locking when resetting
    fbl::SinglyLinkedList<fbl::RefPtr<Fence>> fences;
    {
        fbl::AutoLock lock(&fence_mtx_);
        while (!fences_.is_empty()) {
            fences.push_front(fences_.erase(fences_.begin()));
        }
    }
    while (!fences.is_empty()) {
        fences.pop_front()->ClearRef();
    }

    for (auto& config : configs_) {
        config.pending_layers_.clear();
        config.current_layers_.clear();
    }

    // The layer's images have already been handled in CleanUpImageLayerState
    layers_.clear();

    ApplyConfig();

    proxy_->OnClientDead();
}

bool Client::CleanUpImage(Image* image) {
    // Clean up any fences associated with the image
    {
        fbl::AutoLock lock(controller_->mtx());
        if (image) {
            image->ResetFences();
        } else {
            for (auto& image : images_) {
                image.ResetFences();
            }
        }
    }

    // Clean up any layer state associated with the images
    bool current_config_change = false;
    for (auto& layer : layers_) {
        if (layer.pending_image_ && (image == nullptr || layer.pending_image_.get() == image)) {
            layer.pending_image_->DiscardAcquire();
            layer.pending_image_ = nullptr;
        }
        if (image == nullptr) {
            do_early_retire(&layer.waiting_images_, nullptr);
        } else {
            image_node_t* waiting;
            list_for_every_entry(&layer.waiting_images_, waiting, image_node_t, link) {
                if (waiting->self.get() == image) {
                    list_delete(&waiting->link);
                    waiting->self->EarlyRetire();
                    waiting->self.reset();
                    break;
                }
            }
        }
        if (layer.displayed_image_ && (image == nullptr || layer.displayed_image_.get() == image)) {
            {
                fbl::AutoLock lock(controller_->mtx());
                layer.displayed_image_->StartRetire();
            }
            layer.displayed_image_ = nullptr;

            if (layer.current_node_.InContainer()) {
                current_config_change = true;
            }
        }
    }

    // Clean up the image id map
    if (image) {
        images_.erase(*image);
    } else {
        images_.clear();
    }

    return current_config_change;
}

zx_status_t Client::Init(zx_handle_t server_handle) {
    zx_status_t status;

    api_wait_.set_object(server_handle);
    api_wait_.set_trigger(ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED);
    if ((status = api_wait_.Begin(controller_->loop().dispatcher())) != ZX_OK) {
        // Clear the object, since that's used to detect whether or not api_wait_ is inited.
        api_wait_.set_object(ZX_HANDLE_INVALID);
        zxlogf(ERROR, "Failed to start waiting %d\n", status);
        return status;
    }

    server_handle_ = server_handle;

    zx::channel sysmem_allocator_request;
    zx::channel::create(0, &sysmem_allocator_request, &sysmem_allocator_);
    status = controller_->dc()->GetSysmemConnection(std::move(sysmem_allocator_request));
    if (status != ZX_OK) {
        // Not a fatal error, but BufferCollection functions won't work.
        // TODO(ZX-3355) TODO: Fail creation once all drivers implement this.
        zxlogf(ERROR, "GetSysmemConnection failed (continuing) - status: %d\n",
               status);
        sysmem_allocator_.reset();
    }

    mtx_init(&fence_mtx_, mtx_plain);

    return ZX_OK;
}

Client::Client(Controller* controller, ClientProxy* proxy, bool is_vc)
        : controller_(controller), proxy_(proxy), is_vc_(is_vc) { }

Client::~Client() {
    ZX_DEBUG_ASSERT(server_handle_ == ZX_HANDLE_INVALID);
}

void ClientProxy::SetOwnership(bool is_owner) {
    auto task = new async::Task();
    task->set_handler([client_handler = &handler_, is_owner]
                       (async_dispatcher_t* dispatcher, async::Task* task, zx_status_t status) {
            if (status == ZX_OK && client_handler->IsValid()) {
                client_handler->SetOwnership(is_owner);
            }

            delete task;

    });
    task->Post(controller_->loop().dispatcher());
}

void ClientProxy::OnDisplaysChanged(const uint64_t* displays_added,
                                    size_t added_count, const uint64_t* displays_removed,
                                    size_t removed_count) {
    handler_.OnDisplaysChanged(displays_added, added_count, displays_removed, removed_count);
}

void ClientProxy::ReapplyConfig() {
    fbl::AllocChecker ac;
    auto task = new (&ac) async::Task();
    if (!ac.check()) {
        zxlogf(WARN, "Failed to reapply config\n");
        return;
    }

    task->set_handler([client_handler = &handler_]
                       (async_dispatcher_t* dispatcher, async::Task* task, zx_status_t status) {
            if (status == ZX_OK && client_handler->IsValid()) {
                client_handler->ApplyConfig();
            }

            delete task;

    });
    task->Post(controller_->loop().dispatcher());
}

void ClientProxy::OnDisplayVsync(uint64_t display_id, zx_time_t timestamp,
                                 uint64_t* image_ids, size_t count) {
    ZX_DEBUG_ASSERT(mtx_trylock(controller_->mtx()) == thrd_busy);

    if (!enable_vsync_) {
        return;
    }
    uint32_t size = static_cast<uint32_t>(sizeof(fuchsia_hardware_display_ControllerVsyncEvent) +
                                          sizeof(uint64_t) * count);
    uint8_t data[size];

    fuchsia_hardware_display_ControllerVsyncEvent* msg =
        reinterpret_cast<fuchsia_hardware_display_ControllerVsyncEvent*>(data);
    msg->hdr = {};
    msg->hdr.ordinal = fuchsia_hardware_display_ControllerVsyncOrdinal;
    msg->display_id = display_id;
    msg->timestamp = timestamp;
    msg->images.count = count;
    msg->images.data = reinterpret_cast<void*>(FIDL_ALLOC_PRESENT);

    memcpy(msg + 1, image_ids, sizeof(uint64_t) * count);

    zx_status_t status = server_channel_.write(0, data, size, nullptr, 0);
    if (status != ZX_OK) {
        zxlogf(WARN, "Failed to send vsync event %d\n", status);
    }
}

void ClientProxy::OnClientDead() {
    controller_->OnClientDead(this);
    // After OnClientDead, there won't be any more vsync calls. Since that is the only use of
    // the channel off of the loop thread, there's no need to worry about synchronization.
    server_channel_.reset();
}

void ClientProxy::Close() {
    if (controller_->current_thread_is_loop()) {
        handler_.TearDown();
    } else {
        mtx_t mtx;
        mtx_init(&mtx, mtx_plain);
        cnd_t cnd;
        cnd_init(&cnd);
        bool done = false;

        mtx_lock(&mtx);
        auto task = new async::Task();
        task->set_handler([client_handler = &handler_,
                           cnd_ptr = &cnd, mtx_ptr = &mtx, done_ptr = &done]
                           (async_dispatcher_t* dispatcher, async::Task* task, zx_status_t status) {
                mtx_lock(mtx_ptr);

                client_handler->TearDown();

                *done_ptr = true;
                cnd_signal(cnd_ptr);
                mtx_unlock(mtx_ptr);

                delete task;
        });
        if (task->Post(controller_->loop().dispatcher()) != ZX_OK) {
            // Tasks only fail to post if the looper is dead. That shouldn't actually
            // happen, but if it does then it's safe to call Reset on this thread anyway.
            delete task;
            handler_.TearDown();
        } else {
            while (!done) {
                cnd_wait(&cnd, &mtx);
            }
        }
        mtx_unlock(&mtx);
    }
}

zx_status_t ClientProxy::DdkClose(uint32_t flags) {
    printf("DdkClose\n");
    Close();
    return ZX_OK;
}

void ClientProxy::DdkRelease() {
    delete this;
}

zx_status_t ClientProxy::Init(zx::channel server_channel) {
    server_channel_ = std::move(server_channel);
    return handler_.Init(server_channel_.get());
}

ClientProxy::ClientProxy(Controller* controller, bool is_vc)
        : ClientParent(controller->zxdev()),
          controller_(controller), is_vc_(is_vc), handler_(controller_, this, is_vc_) {}

ClientProxy::~ClientProxy() { }

} // namespace display
