/* Copyright (C) 2010 The Android Open Source Project
**
** This software is licensed under the terms of the GNU General Public
** License version 2, as published by the Free Software Foundation, and
** may be copied, distributed, and modified under those terms.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
*/

/* Initialization of the Android-specific DisplayState.
 * Read docs/DISPLAY-STATE.TXT to understand what this
 * is supposed to do.
 */
#include "android-qemu2-glue/display.h"

#include "android/emulator-window.h"
#include "android/globals.h"

extern "C" {
#include "qemu/osdep.h"
#include "qemu/module.h"
#include "sysemu/sysemu.h"
#include "ui/console.h"
}

namespace {

struct DCLExtra : public DisplayChangeListener {
    DCLExtra() { memset(this, 0, sizeof(*this)); }

    QFrameBuffer* fb;
};

}

static DCLExtra* asDcl(DisplayChangeListener* dcl) {
    return static_cast<DCLExtra*>(dcl);
}

/*

TECHNICAL NOTE:

DisplayState <--> QFrameBuffer <--> QEmulator/SDL

*/

/* QFrameBuffer producer callbacks */

/* this is called periodically by the GUI timer to check for updates
 * and poll user events. Use vga_hw_update().
 */
static void android_display_producer_check(void* opaque) {
    /* core: call vga_hw_update(). this will eventually
     * lead to calls to android_display_update()
     */
    (void)opaque;
    graphic_hw_update(NULL);
}

static void android_display_producer_invalidate(void* opaque) {
    (void)opaque;
    graphic_hw_invalidate(NULL);
}

static void android_display_producer_detach(void* opaque) {
    // the framebuffer is being deleted, clean it up in the DCL as well
    if (const auto dcl = static_cast<DCLExtra*>(opaque)) {
        dcl->fb = nullptr;
    }
}

/* QFrameBuffer client callbacks */

/* this is called from dpy_update() each time a hardware framebuffer
 * rectangular update was detected. Send this to the QFrameBuffer.
 */
static void android_display_update(DisplayChangeListener* dcl,
                                   int x,
                                   int y,
                                   int w,
                                   int h) {
    if (QFrameBuffer* qfbuff = asDcl(dcl)->fb) {
        qframebuffer_update(qfbuff, x, y, w, h);
    }
}

static pixman_image_t* get_pixman_image_from_qframebuffer(QFrameBuffer* qf) {
    pixman_format_code_t format =
            qemu_default_pixman_format(qf->bits_per_pixel, true);
    return pixman_image_create_bits(format, qf->width, qf->height,
                                    (uint32_t*)qf->pixels, qf->pitch);
}

static void android_display_switch(DisplayChangeListener* dcl,
                                   DisplaySurface* new_surface) {
    if (QFrameBuffer* qfbuff = asDcl(dcl)->fb) {
        if (android_hw->hw_arc) {
            static pixman_image_t * qfb_image =
                    get_pixman_image_from_qframebuffer(qfbuff);
            pixman_image_composite(PIXMAN_OP_OVER,
                                   new_surface->image, NULL,
                                   qfb_image,
                                   0, 0, 0, 0, 0, 0,
                                   qfbuff->width, qfbuff->height);
        }
        qframebuffer_rotate(qfbuff, 0);
    }
}

static void android_display_refresh(DisplayChangeListener* dcl) {
    if (QFrameBuffer* qfbuff = asDcl(dcl)->fb) {
        qframebuffer_poll(qfbuff);
    }
}

extern void * android_gl_create_context(DisplayChangeListener*, QEMUGLParams *);
extern void android_gl_destroy_context(DisplayChangeListener*, void *);
extern int android_gl_make_context_current(DisplayChangeListener*, void *);
extern void android_gl_scanout_texture(DisplayChangeListener*, uint32_t, bool,
                                       uint32_t, uint32_t, uint32_t, uint32_t,
                                       uint32_t, uint32_t);
extern void android_gl_scanout_flush(DisplayChangeListener *, uint32_t,
                                     uint32_t, uint32_t, uint32_t);

static void android_gl_scanout_disable(DisplayChangeListener *dcl) {
    fprintf(stderr, "stub %s\n", __func__);
}

static QemuConsole* find_graphic_console() {
    // find the first graphic console (Android emulator has only one usually)
    for (int i = 0;; i++) {
        QemuConsole* const c = qemu_console_lookup_by_index(i);
        if (!c) {
            break;
        }
        if (qemu_console_is_graphic(c)) {
            return c;
        }
    }

    return NULL;
}

static int last_graphic_console_index() {
    int last = -1;
    for (int i = 0;; i++) {
        QemuConsole* const c = qemu_console_lookup_by_index(i);
        if (!c) {
            break;
        }
        if (qemu_console_is_graphic(c)) {
            last = i;
        }
    }
    return last;
}

static DisplayChangeListenerOps dclOps = {};

void android_display_init_no_window(QFrameBuffer* qf) {
    // Only need to attach the check and invalidate callbacks in no-window mode
    // to request for a refresh of the framebuffer.
    qframebuffer_set_producer(qf, nullptr, android_display_producer_check,
                              android_display_producer_invalidate, nullptr);
}

bool android_display_init(DisplayState* ds, QFrameBuffer* qf) {
    QemuConsole* con = find_graphic_console();
    if (!con) {
        return false;
    }
    if (android_hw->hw_arc) {
        /* We don't use goldfish_fb in cros now. so
         * just pick up last graphic console */
        int index = last_graphic_console_index();
        if (index < 0) {
            return false;
        }
        console_select(index);
        con = qemu_console_lookup_by_index(index);
        QemuUIInfo info = {
            0, 0,
            (uint32_t)qf->width,
            (uint32_t)qf->height,
        };
        dpy_set_ui_info(con, &info);
    }
    const auto dcl = new DCLExtra();

    qframebuffer_set_producer(qf, dcl,
                              android_display_producer_check,
                              android_display_producer_invalidate,
                              android_display_producer_detach);

    /* Replace the display surface with one with the right dimensions */
    pixman_format_code_t format =
            qemu_default_pixman_format(qf->bits_per_pixel, true);

    auto surface = qemu_create_displaysurface_from(
            qf->width, qf->height, format, qf->pitch, (uint8_t*)qf->pixels);

    dpy_gfx_replace_surface(con, surface);

    /* Register a change listener for it */
    dcl->fb = qf;

    dclOps.dpy_name = "qemu2-glue";
    dclOps.dpy_refresh = &android_display_refresh;
    dclOps.dpy_gfx_update = &android_display_update;
    dclOps.dpy_gfx_switch = &android_display_switch;

    if (android_hw->hw_arc) {
        dclOps.dpy_gl_ctx_create       = &android_gl_create_context;
        dclOps.dpy_gl_ctx_destroy      = &android_gl_destroy_context;
        dclOps.dpy_gl_ctx_make_current = &android_gl_make_context_current;
        dclOps.dpy_gl_scanout_disable  = &android_gl_scanout_disable;
        dclOps.dpy_gl_scanout_texture  = &android_gl_scanout_texture;
        dclOps.dpy_gl_update           = &android_gl_scanout_flush;

        dcl->con = con;
    }

    dcl->ops = &dclOps;
    register_displaychangelistener(dcl);

    return true;
}

extern "C" void sdl_display_early_init(DisplayOptions* opts) {
    if (opts->gl && android_hw->hw_arc) {
        display_opengl = 1;
    }
}

extern "C" int sdl_display_init(DisplayState* ds, DisplayOptions* opts) {
    (void)opts;

    EmulatorWindow* const emulator = emulator_window_get();
    if (emulator->opts->no_window) {
        return true;
    }

    return android_display_init(ds, qframebuffer_fifo_get());
}

static QemuDisplay qemu_display_android = {
    .type       = DISPLAY_TYPE_SDL,
    .early_init = sdl_display_early_init,
    .init       = sdl_display_init,
};

static void register_android_ui(void)
{
    qemu_display_register(&qemu_display_android);
}

type_init(register_android_ui);

