/*
 * QEMU Apple ParavirtualizedGraphics.framework device
 *
 * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * ParavirtualizedGraphics.framework is a set of libraries that macOS provides
 * which implements 3d graphics passthrough to the host as well as a
 * proprietary guest communication channel to drive it. This device model
 * implements support to drive that library from within QEMU.
 */

#include "qemu/osdep.h"
#include "qemu/lockable.h"
#include "qemu/cutils.h"
#include "qemu/log.h"
#include "qapi/visitor.h"
#include "qapi/error.h"
#include "block/aio-wait.h"
#include "system/address-spaces.h"
#include "system/dma.h"
#include "migration/blocker.h"
#include "ui/console.h"
#include "apple-gfx.h"
#include "trace.h"

#include <mach/mach.h>
#include <mach/mach_vm.h>
#include <dispatch/dispatch.h>

#import <ParavirtualizedGraphics/ParavirtualizedGraphics.h>

static const AppleGFXDisplayMode apple_gfx_default_modes[] = {
    { 1920, 1080, 60 },
    { 1440, 1080, 60 },
    { 1280, 1024, 60 },
};

static Error *apple_gfx_mig_blocker;
static uint32_t next_pgdisplay_serial_num = 1;

static dispatch_queue_t get_background_queue(void)
{
    return dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
}

/* ------ PGTask and task operations: new/destroy/map/unmap ------ */

/*
 * This implements the type declared in <ParavirtualizedGraphics/PGDevice.h>
 * which is opaque from the framework's point of view. It is used in callbacks
 * in the form of its typedef PGTask_t, which also already exists in the
 * framework headers.
 *
 * A "task" in PVG terminology represents a host-virtual contiguous address
 * range which is reserved in a large chunk on task creation. The mapMemory
 * callback then requests ranges of guest system memory (identified by their
 * GPA) to be mapped into subranges of this reserved address space.
 * This type of operation isn't well-supported by QEMU's memory subsystem,
 * but it is fortunately trivial to achieve with Darwin's mach_vm_remap() call,
 * which allows us to refer to the same backing memory via multiple virtual
 * address ranges. The Mach VM APIs are therefore used throughout for managing
 * task memory.
 */
struct PGTask_s {
    QTAILQ_ENTRY(PGTask_s) node;
    AppleGFXState *s;
    mach_vm_address_t address;
    uint64_t len;
    /*
     * All unique MemoryRegions for which a mapping has been created in this
     * task, and on which we have thus called memory_region_ref(). There are
     * usually very few regions of system RAM in total, so we expect this array
     * to be very short. Therefore, no need for sorting or fancy search
     * algorithms, linear search will do.
     * Protected by AppleGFXState's task_mutex.
     */
    GPtrArray *mapped_regions;
};

static PGTask_t *apple_gfx_new_task(AppleGFXState *s, uint64_t len)
{
    mach_vm_address_t task_mem;
    PGTask_t *task;
    kern_return_t r;

    r = mach_vm_allocate(mach_task_self(), &task_mem, len, VM_FLAGS_ANYWHERE);
    if (r != KERN_SUCCESS) {
        return NULL;
    }

    task = g_new0(PGTask_t, 1);
    task->s = s;
    task->address = task_mem;
    task->len = len;
    task->mapped_regions = g_ptr_array_sized_new(2 /* Usually enough */);

    QEMU_LOCK_GUARD(&s->task_mutex);
    QTAILQ_INSERT_TAIL(&s->tasks, task, node);

    return task;
}

static void apple_gfx_destroy_task(AppleGFXState *s, PGTask_t *task)
{
    GPtrArray *regions = task->mapped_regions;
    MemoryRegion *region;
    size_t i;

    for (i = 0; i < regions->len; ++i) {
        region = g_ptr_array_index(regions, i);
        memory_region_unref(region);
    }
    g_ptr_array_unref(regions);

    mach_vm_deallocate(mach_task_self(), task->address, task->len);

    QEMU_LOCK_GUARD(&s->task_mutex);
    QTAILQ_REMOVE(&s->tasks, task, node);
    g_free(task);
}

void *apple_gfx_host_ptr_for_gpa_range(uint64_t guest_physical,
                                       uint64_t length, bool read_only,
                                       MemoryRegion **mapping_in_region)
{
    MemoryRegion *ram_region;
    char *host_ptr;
    hwaddr ram_region_offset = 0;
    hwaddr ram_region_length = length;

    ram_region = address_space_translate(&address_space_memory,
                                         guest_physical,
                                         &ram_region_offset,
                                         &ram_region_length, !read_only,
                                         MEMTXATTRS_UNSPECIFIED);

    if (!ram_region || ram_region_length < length ||
        !memory_access_is_direct(ram_region, !read_only,
				 MEMTXATTRS_UNSPECIFIED)) {
        return NULL;
    }

    host_ptr = memory_region_get_ram_ptr(ram_region);
    if (!host_ptr) {
        return NULL;
    }
    host_ptr += ram_region_offset;
    *mapping_in_region = ram_region;
    return host_ptr;
}

static bool apple_gfx_task_map_memory(AppleGFXState *s, PGTask_t *task,
                                      uint64_t virtual_offset,
                                      PGPhysicalMemoryRange_t *ranges,
                                      uint32_t range_count, bool read_only)
{
    kern_return_t r;
    void *source_ptr;
    mach_vm_address_t target;
    vm_prot_t cur_protection, max_protection;
    bool success = true;
    MemoryRegion *region;

    RCU_READ_LOCK_GUARD();
    QEMU_LOCK_GUARD(&s->task_mutex);

    trace_apple_gfx_map_memory(task, range_count, virtual_offset, read_only);
    for (int i = 0; i < range_count; i++) {
        PGPhysicalMemoryRange_t *range = &ranges[i];

        target = task->address + virtual_offset;
        virtual_offset += range->physicalLength;

        trace_apple_gfx_map_memory_range(i, range->physicalAddress,
                                         range->physicalLength);

        region = NULL;
        source_ptr = apple_gfx_host_ptr_for_gpa_range(range->physicalAddress,
                                                      range->physicalLength,
                                                      read_only, &region);
        if (!source_ptr) {
            success = false;
            continue;
        }

        if (!g_ptr_array_find(task->mapped_regions, region, NULL)) {
            g_ptr_array_add(task->mapped_regions, region);
            memory_region_ref(region);
        }

        cur_protection = 0;
        max_protection = 0;
        /* Map guest RAM at range->physicalAddress into PG task memory range */
        r = mach_vm_remap(mach_task_self(),
                          &target, range->physicalLength, vm_page_size - 1,
                          VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE,
                          mach_task_self(), (mach_vm_address_t)source_ptr,
                          false /* shared mapping, no copy */,
                          &cur_protection, &max_protection,
                          VM_INHERIT_COPY);
        trace_apple_gfx_remap(r, source_ptr, target);
        g_assert(r == KERN_SUCCESS);
    }

    return success;
}

static void apple_gfx_task_unmap_memory(AppleGFXState *s, PGTask_t *task,
                                        uint64_t virtual_offset, uint64_t length)
{
    kern_return_t r;
    mach_vm_address_t range_address;

    trace_apple_gfx_unmap_memory(task, virtual_offset, length);

    /*
     * Replace task memory range with fresh 0 pages, undoing the mapping
     * from guest RAM.
     */
    range_address = task->address + virtual_offset;
    r = mach_vm_allocate(mach_task_self(), &range_address, length,
                         VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE);
    g_assert(r == KERN_SUCCESS);
}

/* ------ Rendering and frame management ------ */

static void apple_gfx_render_frame_completed_bh(void *opaque);

static void apple_gfx_render_new_frame(AppleGFXState *s)
{
    bool managed_texture = s->using_managed_texture_storage;
    uint32_t width = surface_width(s->surface);
    uint32_t height = surface_height(s->surface);
    MTLRegion region = MTLRegionMake2D(0, 0, width, height);
    id<MTLCommandBuffer> command_buffer = [s->mtl_queue commandBuffer];
    id<MTLTexture> texture = s->texture;

    assert(bql_locked());
    [texture retain];
    [command_buffer retain];

    s->rendering_frame_width = width;
    s->rendering_frame_height = height;

    dispatch_async(get_background_queue(), ^{
        /*
         * This is not safe to call from the BQL/BH due to PVG-internal locks
         * causing deadlocks.
         */
        bool r = [s->pgdisp encodeCurrentFrameToCommandBuffer:command_buffer
                                                 texture:texture
                                                  region:region];
        if (!r) {
            [texture release];
            [command_buffer release];
            qemu_log_mask(LOG_GUEST_ERROR,
                          "%s: encodeCurrentFrameToCommandBuffer:texture:region: "
                          "failed\n", __func__);
            bql_lock();
            --s->pending_frames;
            if (s->pending_frames > 0) {
                apple_gfx_render_new_frame(s);
            }
            bql_unlock();
            return;
        }

        if (managed_texture) {
            /* "Managed" textures exist in both VRAM and RAM and must be synced. */
            id<MTLBlitCommandEncoder> blit = [command_buffer blitCommandEncoder];
            [blit synchronizeResource:texture];
            [blit endEncoding];
        }
        [texture release];
        [command_buffer addCompletedHandler:
            ^(id<MTLCommandBuffer> cb)
            {
                aio_bh_schedule_oneshot(qemu_get_aio_context(),
                                        apple_gfx_render_frame_completed_bh, s);
            }];
        [command_buffer commit];
        [command_buffer release];
    });
}

static void copy_mtl_texture_to_surface_mem(id<MTLTexture> texture, void *vram)
{
    /*
     * TODO: Skip this entirely on a pure Metal or headless/guest-only
     * rendering path, else use a blit command encoder? Needs careful
     * (double?) buffering design.
     */
    size_t width = texture.width, height = texture.height;
    MTLRegion region = MTLRegionMake2D(0, 0, width, height);
    [texture getBytes:vram
          bytesPerRow:(width * 4)
        bytesPerImage:(width * height * 4)
           fromRegion:region
          mipmapLevel:0
                slice:0];
}

static void apple_gfx_render_frame_completed_bh(void *opaque)
{
    AppleGFXState *s = opaque;

    @autoreleasepool {
        --s->pending_frames;
        assert(s->pending_frames >= 0);

        /* Only update display if mode hasn't changed since we started rendering. */
        if (s->rendering_frame_width == surface_width(s->surface) &&
            s->rendering_frame_height == surface_height(s->surface)) {
            copy_mtl_texture_to_surface_mem(s->texture, surface_data(s->surface));
            if (s->gfx_update_requested) {
                s->gfx_update_requested = false;
                dpy_gfx_update_full(s->con);
                graphic_hw_update_done(s->con);
                s->new_frame_ready = false;
            } else {
                s->new_frame_ready = true;
            }
        }
        if (s->pending_frames > 0) {
            apple_gfx_render_new_frame(s);
        }
    }
}

static void apple_gfx_fb_update_display(void *opaque)
{
    AppleGFXState *s = opaque;

    assert(bql_locked());
    if (s->new_frame_ready) {
        dpy_gfx_update_full(s->con);
        s->new_frame_ready = false;
        graphic_hw_update_done(s->con);
    } else if (s->pending_frames > 0) {
        s->gfx_update_requested = true;
    } else {
        graphic_hw_update_done(s->con);
    }
}

static const GraphicHwOps apple_gfx_fb_ops = {
    .gfx_update = apple_gfx_fb_update_display,
    .gfx_update_async = true,
};

/* ------ Mouse cursor and display mode setting ------ */

static void set_mode(AppleGFXState *s, uint32_t width, uint32_t height)
{
    MTLTextureDescriptor *textureDescriptor;

    if (s->surface &&
        width == surface_width(s->surface) &&
        height == surface_height(s->surface)) {
        return;
    }

    [s->texture release];

    s->surface = qemu_create_displaysurface(width, height);

    @autoreleasepool {
        textureDescriptor =
            [MTLTextureDescriptor
                texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
                                             width:width
                                            height:height
                                         mipmapped:NO];
        textureDescriptor.usage = s->pgdisp.minimumTextureUsage;
        s->texture = [s->mtl newTextureWithDescriptor:textureDescriptor];
        s->using_managed_texture_storage =
            (s->texture.storageMode == MTLStorageModeManaged);
    }

    dpy_gfx_replace_surface(s->con, s->surface);
}

static void update_cursor(AppleGFXState *s)
{
    assert(bql_locked());
    dpy_mouse_set(s->con, s->pgdisp.cursorPosition.x,
                  s->pgdisp.cursorPosition.y, qatomic_read(&s->cursor_show));
}

static void update_cursor_bh(void *opaque)
{
    AppleGFXState *s = opaque;
    update_cursor(s);
}

typedef struct AppleGFXSetCursorGlyphJob {
    AppleGFXState *s;
    NSBitmapImageRep *glyph;
    PGDisplayCoord_t hotspot;
} AppleGFXSetCursorGlyphJob;

static void set_cursor_glyph(void *opaque)
{
    AppleGFXSetCursorGlyphJob *job = opaque;
    AppleGFXState *s = job->s;
    NSBitmapImageRep *glyph = job->glyph;
    uint32_t bpp = glyph.bitsPerPixel;
    size_t width = glyph.pixelsWide;
    size_t height = glyph.pixelsHigh;
    size_t padding_bytes_per_row = glyph.bytesPerRow - width * 4;
    const uint8_t* px_data = glyph.bitmapData;

    trace_apple_gfx_cursor_set(bpp, width, height);

    if (s->cursor) {
        cursor_unref(s->cursor);
        s->cursor = NULL;
    }

    if (bpp == 32) { /* Shouldn't be anything else, but just to be safe... */
        s->cursor = cursor_alloc(width, height);
        s->cursor->hot_x = job->hotspot.x;
        s->cursor->hot_y = job->hotspot.y;

        uint32_t *dest_px = s->cursor->data;

        for (size_t y = 0; y < height; ++y) {
            for (size_t x = 0; x < width; ++x) {
                /*
                 * NSBitmapImageRep's red & blue channels are swapped
                 * compared to QEMUCursor's.
                 */
                *dest_px =
                    (px_data[0] << 16u) |
                    (px_data[1] <<  8u) |
                    (px_data[2] <<  0u) |
                    (px_data[3] << 24u);
                ++dest_px;
                px_data += 4;
            }
            px_data += padding_bytes_per_row;
        }
        dpy_cursor_define(s->con, s->cursor);
        update_cursor(s);
    }
    [glyph release];

    g_free(job);
}

/* ------ DMA (device reading system memory) ------ */

typedef struct AppleGFXReadMemoryJob {
    QemuEvent event;
    hwaddr physical_address;
    uint64_t length;
    void *dst;
    bool success;
} AppleGFXReadMemoryJob;

static void apple_gfx_do_read_memory(void *opaque)
{
    AppleGFXReadMemoryJob *job = opaque;
    MemTxResult r;

    r = dma_memory_read(&address_space_memory, job->physical_address,
                        job->dst, job->length, MEMTXATTRS_UNSPECIFIED);
    job->success = (r == MEMTX_OK);

    qemu_event_set(&job->event);
}

static bool apple_gfx_read_memory(AppleGFXState *s, hwaddr physical_address,
                                  uint64_t length, void *dst)
{
    AppleGFXReadMemoryJob job = {
        .physical_address = physical_address, .length = length, .dst = dst
    };

    trace_apple_gfx_read_memory(physical_address, length, dst);

    /* Performing DMA requires BQL, so do it in a BH. */
    qemu_event_init(&job.event, 0);
    aio_bh_schedule_oneshot(qemu_get_aio_context(),
                            apple_gfx_do_read_memory, &job);
    qemu_event_wait(&job.event);
    qemu_event_destroy(&job.event);
    return job.success;
}

/* ------ Memory-mapped device I/O operations ------ */

typedef struct AppleGFXIOJob {
    AppleGFXState *state;
    uint64_t offset;
    uint64_t value;
    bool completed;
} AppleGFXIOJob;

static void apple_gfx_do_read(void *opaque)
{
    AppleGFXIOJob *job = opaque;
    job->value = [job->state->pgdev mmioReadAtOffset:job->offset];
    qatomic_set(&job->completed, true);
    aio_wait_kick();
}

static uint64_t apple_gfx_read(void *opaque, hwaddr offset, unsigned size)
{
    AppleGFXIOJob job = {
        .state = opaque,
        .offset = offset,
        .completed = false,
    };
    dispatch_queue_t queue = get_background_queue();

    dispatch_async_f(queue, &job, apple_gfx_do_read);
    AIO_WAIT_WHILE(NULL, !qatomic_read(&job.completed));

    trace_apple_gfx_read(offset, job.value);
    return job.value;
}

static void apple_gfx_do_write(void *opaque)
{
    AppleGFXIOJob *job = opaque;
    [job->state->pgdev mmioWriteAtOffset:job->offset value:job->value];
    qatomic_set(&job->completed, true);
    aio_wait_kick();
}

static void apple_gfx_write(void *opaque, hwaddr offset, uint64_t val,
                            unsigned size)
{
    /*
     * The methods mmioReadAtOffset: and especially mmioWriteAtOffset: can
     * trigger synchronous operations on other dispatch queues, which in turn
     * may call back out on one or more of the callback blocks. For this reason,
     * and as we are holding the BQL, we invoke the I/O methods on a pool
     * thread and handle AIO tasks while we wait. Any work in the callbacks
     * requiring the BQL will in turn schedule BHs which this thread will
     * process while waiting.
     */
    AppleGFXIOJob job = {
        .state = opaque,
        .offset = offset,
        .value = val,
        .completed = false,
    };
    dispatch_queue_t queue = get_background_queue();

    dispatch_async_f(queue, &job, apple_gfx_do_write);
    AIO_WAIT_WHILE(NULL, !qatomic_read(&job.completed));

    trace_apple_gfx_write(offset, val);
}

static const MemoryRegionOps apple_gfx_ops = {
    .read = apple_gfx_read,
    .write = apple_gfx_write,
    .endianness = DEVICE_LITTLE_ENDIAN,
    .valid = {
        .min_access_size = 4,
        .max_access_size = 8,
    },
    .impl = {
        .min_access_size = 4,
        .max_access_size = 4,
    },
};

static size_t apple_gfx_get_default_mmio_range_size(void)
{
    size_t mmio_range_size;
    @autoreleasepool {
        PGDeviceDescriptor *desc = [PGDeviceDescriptor new];
        mmio_range_size = desc.mmioLength;
        [desc release];
    }
    return mmio_range_size;
}

/* ------ Initialisation and startup ------ */

void apple_gfx_common_init(Object *obj, AppleGFXState *s, const char* obj_name)
{
    size_t mmio_range_size = apple_gfx_get_default_mmio_range_size();

    trace_apple_gfx_common_init(obj_name, mmio_range_size);
    memory_region_init_io(&s->iomem_gfx, obj, &apple_gfx_ops, s, obj_name,
                          mmio_range_size);

    /* TODO: PVG framework supports serialising device state: integrate it! */
}

static void apple_gfx_register_task_mapping_handlers(AppleGFXState *s,
                                                     PGDeviceDescriptor *desc)
{
    desc.createTask = ^(uint64_t vmSize, void * _Nullable * _Nonnull baseAddress) {
        PGTask_t *task = apple_gfx_new_task(s, vmSize);
        *baseAddress = (void *)task->address;
        trace_apple_gfx_create_task(vmSize, *baseAddress);
        return task;
    };

    desc.destroyTask = ^(PGTask_t * _Nonnull task) {
        trace_apple_gfx_destroy_task(task, task->mapped_regions->len);

        apple_gfx_destroy_task(s, task);
    };

    desc.mapMemory = ^bool(PGTask_t * _Nonnull task, uint32_t range_count,
                           uint64_t virtual_offset, bool read_only,
                           PGPhysicalMemoryRange_t * _Nonnull ranges) {
        return apple_gfx_task_map_memory(s, task, virtual_offset,
                                         ranges, range_count, read_only);
    };

    desc.unmapMemory = ^bool(PGTask_t * _Nonnull task, uint64_t virtual_offset,
                             uint64_t length) {
        apple_gfx_task_unmap_memory(s, task, virtual_offset, length);
        return true;
    };

    desc.readMemory = ^bool(uint64_t physical_address, uint64_t length,
                            void * _Nonnull dst) {
        return apple_gfx_read_memory(s, physical_address, length, dst);
    };
}

static void new_frame_handler_bh(void *opaque)
{
    AppleGFXState *s = opaque;

    /* Drop frames if guest gets too far ahead. */
    if (s->pending_frames >= 2) {
        return;
    }
    ++s->pending_frames;
    if (s->pending_frames > 1) {
        return;
    }

    @autoreleasepool {
        apple_gfx_render_new_frame(s);
    }
}

static PGDisplayDescriptor *apple_gfx_prepare_display_descriptor(AppleGFXState *s)
{
    PGDisplayDescriptor *disp_desc = [PGDisplayDescriptor new];

    disp_desc.name = @"QEMU display";
    disp_desc.sizeInMillimeters = NSMakeSize(400., 300.); /* A 20" display */
    disp_desc.queue = dispatch_get_main_queue();
    disp_desc.newFrameEventHandler = ^(void) {
        trace_apple_gfx_new_frame();
        aio_bh_schedule_oneshot(qemu_get_aio_context(), new_frame_handler_bh, s);
    };
    disp_desc.modeChangeHandler = ^(PGDisplayCoord_t sizeInPixels,
                                    OSType pixelFormat) {
        trace_apple_gfx_mode_change(sizeInPixels.x, sizeInPixels.y);

        BQL_LOCK_GUARD();
        set_mode(s, sizeInPixels.x, sizeInPixels.y);
    };
    disp_desc.cursorGlyphHandler = ^(NSBitmapImageRep *glyph,
                                     PGDisplayCoord_t hotspot) {
        AppleGFXSetCursorGlyphJob *job = g_malloc0(sizeof(*job));
        job->s = s;
        job->glyph = glyph;
        job->hotspot = hotspot;
        [glyph retain];
        aio_bh_schedule_oneshot(qemu_get_aio_context(),
                                set_cursor_glyph, job);
    };
    disp_desc.cursorShowHandler = ^(BOOL show) {
        trace_apple_gfx_cursor_show(show);
        qatomic_set(&s->cursor_show, show);
        aio_bh_schedule_oneshot(qemu_get_aio_context(),
                                update_cursor_bh, s);
    };
    disp_desc.cursorMoveHandler = ^(void) {
        trace_apple_gfx_cursor_move();
        aio_bh_schedule_oneshot(qemu_get_aio_context(),
                                update_cursor_bh, s);
    };

    return disp_desc;
}

static NSArray<PGDisplayMode *> *apple_gfx_create_display_mode_array(
    const AppleGFXDisplayMode display_modes[], uint32_t display_mode_count)
{
    PGDisplayMode *mode_obj;
    NSMutableArray<PGDisplayMode *> *mode_array =
        [[NSMutableArray alloc] initWithCapacity:display_mode_count];

    for (unsigned i = 0; i < display_mode_count; i++) {
        const AppleGFXDisplayMode *mode = &display_modes[i];
        trace_apple_gfx_display_mode(i, mode->width_px, mode->height_px);
        PGDisplayCoord_t mode_size = { mode->width_px, mode->height_px };

        mode_obj =
            [[PGDisplayMode alloc] initWithSizeInPixels:mode_size
                                        refreshRateInHz:mode->refresh_rate_hz];
        [mode_array addObject:mode_obj];
        [mode_obj release];
    }

    return mode_array;
}

static id<MTLDevice> copy_suitable_metal_device(void)
{
    id<MTLDevice> dev = nil;
    NSArray<id<MTLDevice>> *devs = MTLCopyAllDevices();

    /* Prefer a unified memory GPU. Failing that, pick a non-removable GPU. */
    for (size_t i = 0; i < devs.count; ++i) {
        if (devs[i].hasUnifiedMemory) {
            dev = devs[i];
            break;
        }
        if (!devs[i].removable) {
            dev = devs[i];
        }
    }

    if (dev != nil) {
        [dev retain];
    } else {
        dev = MTLCreateSystemDefaultDevice();
    }
    [devs release];

    return dev;
}

bool apple_gfx_common_realize(AppleGFXState *s, DeviceState *dev,
                              PGDeviceDescriptor *desc, Error **errp)
{
    PGDisplayDescriptor *disp_desc;
    const AppleGFXDisplayMode *display_modes = apple_gfx_default_modes;
    uint32_t num_display_modes = ARRAY_SIZE(apple_gfx_default_modes);
    NSArray<PGDisplayMode *> *mode_array;

    if (apple_gfx_mig_blocker == NULL) {
        error_setg(&apple_gfx_mig_blocker,
                  "Migration state blocked by apple-gfx display device");
        if (migrate_add_blocker(&apple_gfx_mig_blocker, errp) < 0) {
            return false;
        }
    }

    qemu_mutex_init(&s->task_mutex);
    QTAILQ_INIT(&s->tasks);
    s->mtl = copy_suitable_metal_device();
    s->mtl_queue = [s->mtl newCommandQueue];

    desc.device = s->mtl;

    apple_gfx_register_task_mapping_handlers(s, desc);

    s->cursor_show = true;

    s->pgdev = PGNewDeviceWithDescriptor(desc);

    disp_desc = apple_gfx_prepare_display_descriptor(s);
    /*
     * Although the framework does, this integration currently does not support
     * multiple virtual displays connected to a single PV graphics device.
     * It is however possible to create
     * more than one instance of the device, each with one display. The macOS
     * guest will ignore these displays if they share the same serial number,
     * so ensure each instance gets a unique one.
     */
    s->pgdisp = [s->pgdev newDisplayWithDescriptor:disp_desc
                                              port:0
                                         serialNum:next_pgdisplay_serial_num++];
    [disp_desc release];

    if (s->display_modes != NULL && s->num_display_modes > 0) {
        trace_apple_gfx_common_realize_modes_property(s->num_display_modes);
        display_modes = s->display_modes;
        num_display_modes = s->num_display_modes;
    }
    s->pgdisp.modeList = mode_array =
        apple_gfx_create_display_mode_array(display_modes, num_display_modes);
    [mode_array release];

    s->con = graphic_console_init(dev, 0, &apple_gfx_fb_ops, s);
    return true;
}

/* ------ Display mode list device property ------ */

static void apple_gfx_get_display_mode(Object *obj, Visitor *v,
                                       const char *name, void *opaque,
                                       Error **errp)
{
    Property *prop = opaque;
    AppleGFXDisplayMode *mode = object_field_prop_ptr(obj, prop);
    /* 3 uint16s (max 5 digits) + 2 separator characters + nul. */
    char buffer[5 * 3 + 2 + 1];
    char *pos = buffer;

    int rc = snprintf(buffer, sizeof(buffer),
                      "%"PRIu16"x%"PRIu16"@%"PRIu16,
                      mode->width_px, mode->height_px,
                      mode->refresh_rate_hz);
    assert(rc < sizeof(buffer));

    visit_type_str(v, name, &pos, errp);
}

static void apple_gfx_set_display_mode(Object *obj, Visitor *v,
                                       const char *name, void *opaque,
                                       Error **errp)
{
    Property *prop = opaque;
    AppleGFXDisplayMode *mode = object_field_prop_ptr(obj, prop);
    const char *endptr;
    g_autofree char *str = NULL;
    int ret;
    int val;

    if (!visit_type_str(v, name, &str, errp)) {
        return;
    }

    endptr = str;

    ret = qemu_strtoi(endptr, &endptr, 10, &val);
    if (ret || val > UINT16_MAX || val <= 0) {
        error_setg(errp, "width in '%s' must be a decimal integer number"
                         " of pixels in the range 1..65535", name);
        return;
    }
    mode->width_px = val;
    if (*endptr != 'x') {
        goto separator_error;
    }

    ret = qemu_strtoi(endptr + 1, &endptr, 10, &val);
    if (ret || val > UINT16_MAX || val <= 0) {
        error_setg(errp, "height in '%s' must be a decimal integer number"
                         " of pixels in the range 1..65535", name);
        return;
    }
    mode->height_px = val;
    if (*endptr != '@') {
        goto separator_error;
    }

    ret = qemu_strtoi(endptr + 1, &endptr, 10, &val);
    if (ret || val > UINT16_MAX || val <= 0) {
        error_setg(errp, "refresh rate in '%s'"
                         " must be a positive decimal integer (Hertz)", name);
        return;
    }
    mode->refresh_rate_hz = val;
    return;

separator_error:
    error_setg(errp,
               "Each display mode takes the format '<width>x<height>@<rate>'");
}

const PropertyInfo qdev_prop_apple_gfx_display_mode = {
    .type  = "display_mode",
    .description =
        "Display mode in pixels and Hertz, as <width>x<height>@<refresh-rate> "
        "Example: 3840x2160@60",
    .get   = apple_gfx_get_display_mode,
    .set   = apple_gfx_set_display_mode,
};
