/*
 *  QEMU model of the Milkymist texture mapping unit.
 *
 *  Copyright (c) 2010 Michael Walle <michael@walle.cc>
 *  Copyright (c) 2010 Sebastien Bourdeauducq
 *                       <sebastien.bourdeauducq@lekernel.net>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 *
 *
 * Specification available at:
 *   http://milkymist.walle.cc/socdoc/tmu2.pdf
 *
 */

#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/sysbus.h"
#include "trace.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "qemu/module.h"
#include "qapi/error.h"
#include "hw/display/milkymist_tmu2.h"

#include <X11/Xlib.h>
#include <epoxy/gl.h>
#include <epoxy/glx.h>

enum {
    R_CTL = 0,
    R_HMESHLAST,
    R_VMESHLAST,
    R_BRIGHTNESS,
    R_CHROMAKEY,
    R_VERTICESADDR,
    R_TEXFBUF,
    R_TEXHRES,
    R_TEXVRES,
    R_TEXHMASK,
    R_TEXVMASK,
    R_DSTFBUF,
    R_DSTHRES,
    R_DSTVRES,
    R_DSTHOFFSET,
    R_DSTVOFFSET,
    R_DSTSQUAREW,
    R_DSTSQUAREH,
    R_ALPHA,
    R_MAX
};

enum {
    CTL_START_BUSY  = (1<<0),
    CTL_CHROMAKEY   = (1<<1),
};

enum {
    MAX_BRIGHTNESS = 63,
    MAX_ALPHA      = 63,
};

enum {
    MESH_MAXSIZE = 128,
};

struct vertex {
    int x;
    int y;
} QEMU_PACKED;

#define TYPE_MILKYMIST_TMU2 "milkymist-tmu2"
#define MILKYMIST_TMU2(obj) \
    OBJECT_CHECK(MilkymistTMU2State, (obj), TYPE_MILKYMIST_TMU2)

struct MilkymistTMU2State {
    SysBusDevice parent_obj;

    MemoryRegion regs_region;
    Chardev *chr;
    qemu_irq irq;

    uint32_t regs[R_MAX];

    Display *dpy;
    GLXFBConfig glx_fb_config;
    GLXContext glx_context;
};
typedef struct MilkymistTMU2State MilkymistTMU2State;

static const int glx_fbconfig_attr[] = {
    GLX_GREEN_SIZE, 5,
    GLX_GREEN_SIZE, 6,
    GLX_BLUE_SIZE, 5,
    None
};

static int tmu2_glx_init(MilkymistTMU2State *s)
{
    GLXFBConfig *configs;
    int nelements;

    s->dpy = XOpenDisplay(NULL); /* FIXME: call XCloseDisplay() */
    if (s->dpy == NULL) {
        return 1;
    }

    configs = glXChooseFBConfig(s->dpy, 0, glx_fbconfig_attr, &nelements);
    if (configs == NULL) {
        return 1;
    }

    s->glx_fb_config = *configs;
    XFree(configs);

    /* FIXME: call glXDestroyContext() */
    s->glx_context = glXCreateNewContext(s->dpy, s->glx_fb_config,
            GLX_RGBA_TYPE, NULL, 1);
    if (s->glx_context == NULL) {
        return 1;
    }

    return 0;
}

static void tmu2_gl_map(struct vertex *mesh, int texhres, int texvres,
        int hmeshlast, int vmeshlast, int ho, int vo, int sw, int sh)
{
    int x, y;
    int x0, y0, x1, y1;
    int u0, v0, u1, v1, u2, v2, u3, v3;
    double xscale = 1.0 / ((double)(64 * texhres));
    double yscale = 1.0 / ((double)(64 * texvres));

    glLoadIdentity();
    glTranslatef(ho, vo, 0);
    glEnable(GL_TEXTURE_2D);
    glBegin(GL_QUADS);

    for (y = 0; y < vmeshlast; y++) {
        y0 = y * sh;
        y1 = y0 + sh;
        for (x = 0; x < hmeshlast; x++) {
            x0 = x * sw;
            x1 = x0 + sw;

            u0 = be32_to_cpu(mesh[MESH_MAXSIZE * y + x].x);
            v0 = be32_to_cpu(mesh[MESH_MAXSIZE * y + x].y);
            u1 = be32_to_cpu(mesh[MESH_MAXSIZE * y + x + 1].x);
            v1 = be32_to_cpu(mesh[MESH_MAXSIZE * y + x + 1].y);
            u2 = be32_to_cpu(mesh[MESH_MAXSIZE * (y + 1) + x + 1].x);
            v2 = be32_to_cpu(mesh[MESH_MAXSIZE * (y + 1) + x + 1].y);
            u3 = be32_to_cpu(mesh[MESH_MAXSIZE * (y + 1) + x].x);
            v3 = be32_to_cpu(mesh[MESH_MAXSIZE * (y + 1) + x].y);

            glTexCoord2d(((double)u0) * xscale, ((double)v0) * yscale);
            glVertex3i(x0, y0, 0);
            glTexCoord2d(((double)u1) * xscale, ((double)v1) * yscale);
            glVertex3i(x1, y0, 0);
            glTexCoord2d(((double)u2) * xscale, ((double)v2) * yscale);
            glVertex3i(x1, y1, 0);
            glTexCoord2d(((double)u3) * xscale, ((double)v3) * yscale);
            glVertex3i(x0, y1, 0);
        }
    }

    glEnd();
}

static void tmu2_start(MilkymistTMU2State *s)
{
    int pbuffer_attrib[6] = {
        GLX_PBUFFER_WIDTH,
        0,
        GLX_PBUFFER_HEIGHT,
        0,
        GLX_PRESERVED_CONTENTS,
        True
    };

    GLXPbuffer pbuffer;
    GLuint texture;
    void *fb;
    hwaddr fb_len;
    void *mesh;
    hwaddr mesh_len;
    float m;

    trace_milkymist_tmu2_start();

    /* Create and set up a suitable OpenGL context */
    pbuffer_attrib[1] = s->regs[R_DSTHRES];
    pbuffer_attrib[3] = s->regs[R_DSTVRES];
    pbuffer = glXCreatePbuffer(s->dpy, s->glx_fb_config, pbuffer_attrib);
    glXMakeContextCurrent(s->dpy, pbuffer, pbuffer, s->glx_context);

    /* Fixup endianness. TODO: would it work on BE hosts? */
    glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
    glPixelStorei(GL_PACK_SWAP_BYTES, 1);

    /* Row alignment */
    glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
    glPixelStorei(GL_PACK_ALIGNMENT, 2);

    /* Read the QEMU source framebuffer into an OpenGL texture */
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    fb_len = 2ULL * s->regs[R_TEXHRES] * s->regs[R_TEXVRES];
    fb = cpu_physical_memory_map(s->regs[R_TEXFBUF], &fb_len, 0);
    if (fb == NULL) {
        glDeleteTextures(1, &texture);
        glXMakeContextCurrent(s->dpy, None, None, NULL);
        glXDestroyPbuffer(s->dpy, pbuffer);
        return;
    }
    glTexImage2D(GL_TEXTURE_2D, 0, 3, s->regs[R_TEXHRES], s->regs[R_TEXVRES],
            0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, fb);
    cpu_physical_memory_unmap(fb, fb_len, 0, fb_len);

    /* Set up texturing options */
    /* WARNING:
     * Many cases of TMU2 masking are not supported by OpenGL.
     * We only implement the most common ones:
     *  - full bilinear filtering vs. nearest texel
     *  - texture clamping vs. texture wrapping
     */
    if ((s->regs[R_TEXHMASK] & 0x3f) > 0x20) {
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    } else {
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    }
    if ((s->regs[R_TEXHMASK] >> 6) & s->regs[R_TEXHRES]) {
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    } else {
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    }
    if ((s->regs[R_TEXVMASK] >> 6) & s->regs[R_TEXVRES]) {
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    } else {
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    }

    /* Translucency and decay */
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    m = (float)(s->regs[R_BRIGHTNESS] + 1) / 64.0f;
    glColor4f(m, m, m, (float)(s->regs[R_ALPHA] + 1) / 64.0f);

    /* Read the QEMU dest. framebuffer into the OpenGL framebuffer */
    fb_len = 2ULL * s->regs[R_DSTHRES] * s->regs[R_DSTVRES];
    fb = cpu_physical_memory_map(s->regs[R_DSTFBUF], &fb_len, 0);
    if (fb == NULL) {
        glDeleteTextures(1, &texture);
        glXMakeContextCurrent(s->dpy, None, None, NULL);
        glXDestroyPbuffer(s->dpy, pbuffer);
        return;
    }

    glDrawPixels(s->regs[R_DSTHRES], s->regs[R_DSTVRES], GL_RGB,
            GL_UNSIGNED_SHORT_5_6_5, fb);
    cpu_physical_memory_unmap(fb, fb_len, 0, fb_len);
    glViewport(0, 0, s->regs[R_DSTHRES], s->regs[R_DSTVRES]);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0.0, s->regs[R_DSTHRES], 0.0, s->regs[R_DSTVRES], -1.0, 1.0);
    glMatrixMode(GL_MODELVIEW);

    /* Map the texture */
    mesh_len = MESH_MAXSIZE*MESH_MAXSIZE*sizeof(struct vertex);
    mesh = cpu_physical_memory_map(s->regs[R_VERTICESADDR], &mesh_len, 0);
    if (mesh == NULL) {
        glDeleteTextures(1, &texture);
        glXMakeContextCurrent(s->dpy, None, None, NULL);
        glXDestroyPbuffer(s->dpy, pbuffer);
        return;
    }

    tmu2_gl_map((struct vertex *)mesh,
        s->regs[R_TEXHRES], s->regs[R_TEXVRES],
        s->regs[R_HMESHLAST], s->regs[R_VMESHLAST],
        s->regs[R_DSTHOFFSET], s->regs[R_DSTVOFFSET],
        s->regs[R_DSTSQUAREW], s->regs[R_DSTSQUAREH]);
    cpu_physical_memory_unmap(mesh, mesh_len, 0, mesh_len);

    /* Write back the OpenGL framebuffer to the QEMU framebuffer */
    fb_len = 2ULL * s->regs[R_DSTHRES] * s->regs[R_DSTVRES];
    fb = cpu_physical_memory_map(s->regs[R_DSTFBUF], &fb_len, 1);
    if (fb == NULL) {
        glDeleteTextures(1, &texture);
        glXMakeContextCurrent(s->dpy, None, None, NULL);
        glXDestroyPbuffer(s->dpy, pbuffer);
        return;
    }

    glReadPixels(0, 0, s->regs[R_DSTHRES], s->regs[R_DSTVRES], GL_RGB,
            GL_UNSIGNED_SHORT_5_6_5, fb);
    cpu_physical_memory_unmap(fb, fb_len, 1, fb_len);

    /* Free OpenGL allocs */
    glDeleteTextures(1, &texture);
    glXMakeContextCurrent(s->dpy, None, None, NULL);
    glXDestroyPbuffer(s->dpy, pbuffer);

    s->regs[R_CTL] &= ~CTL_START_BUSY;

    trace_milkymist_tmu2_pulse_irq();
    qemu_irq_pulse(s->irq);
}

static uint64_t tmu2_read(void *opaque, hwaddr addr,
                          unsigned size)
{
    MilkymistTMU2State *s = opaque;
    uint32_t r = 0;

    addr >>= 2;
    switch (addr) {
    case R_CTL:
    case R_HMESHLAST:
    case R_VMESHLAST:
    case R_BRIGHTNESS:
    case R_CHROMAKEY:
    case R_VERTICESADDR:
    case R_TEXFBUF:
    case R_TEXHRES:
    case R_TEXVRES:
    case R_TEXHMASK:
    case R_TEXVMASK:
    case R_DSTFBUF:
    case R_DSTHRES:
    case R_DSTVRES:
    case R_DSTHOFFSET:
    case R_DSTVOFFSET:
    case R_DSTSQUAREW:
    case R_DSTSQUAREH:
    case R_ALPHA:
        r = s->regs[addr];
        break;

    default:
        error_report("milkymist_tmu2: read access to unknown register 0x"
                TARGET_FMT_plx, addr << 2);
        break;
    }

    trace_milkymist_tmu2_memory_read(addr << 2, r);

    return r;
}

static void tmu2_check_registers(MilkymistTMU2State *s)
{
    if (s->regs[R_BRIGHTNESS] > MAX_BRIGHTNESS) {
        error_report("milkymist_tmu2: max brightness is %d", MAX_BRIGHTNESS);
    }

    if (s->regs[R_ALPHA] > MAX_ALPHA) {
        error_report("milkymist_tmu2: max alpha is %d", MAX_ALPHA);
    }

    if (s->regs[R_VERTICESADDR] & 0x07) {
        error_report("milkymist_tmu2: vertex mesh address has to be 64-bit "
                "aligned");
    }

    if (s->regs[R_TEXFBUF] & 0x01) {
        error_report("milkymist_tmu2: texture buffer address has to be "
                "16-bit aligned");
    }
}

static void tmu2_write(void *opaque, hwaddr addr, uint64_t value,
                       unsigned size)
{
    MilkymistTMU2State *s = opaque;

    trace_milkymist_tmu2_memory_write(addr, value);

    addr >>= 2;
    switch (addr) {
    case R_CTL:
        s->regs[addr] = value;
        if (value & CTL_START_BUSY) {
            tmu2_start(s);
        }
        break;
    case R_BRIGHTNESS:
    case R_HMESHLAST:
    case R_VMESHLAST:
    case R_CHROMAKEY:
    case R_VERTICESADDR:
    case R_TEXFBUF:
    case R_TEXHRES:
    case R_TEXVRES:
    case R_TEXHMASK:
    case R_TEXVMASK:
    case R_DSTFBUF:
    case R_DSTHRES:
    case R_DSTVRES:
    case R_DSTHOFFSET:
    case R_DSTVOFFSET:
    case R_DSTSQUAREW:
    case R_DSTSQUAREH:
    case R_ALPHA:
        s->regs[addr] = value;
        break;

    default:
        error_report("milkymist_tmu2: write access to unknown register 0x"
                TARGET_FMT_plx, addr << 2);
        break;
    }

    tmu2_check_registers(s);
}

static const MemoryRegionOps tmu2_mmio_ops = {
    .read = tmu2_read,
    .write = tmu2_write,
    .valid = {
        .min_access_size = 4,
        .max_access_size = 4,
    },
    .endianness = DEVICE_NATIVE_ENDIAN,
};

static void milkymist_tmu2_reset(DeviceState *d)
{
    MilkymistTMU2State *s = MILKYMIST_TMU2(d);
    int i;

    for (i = 0; i < R_MAX; i++) {
        s->regs[i] = 0;
    }
}

static void milkymist_tmu2_init(Object *obj)
{
    MilkymistTMU2State *s = MILKYMIST_TMU2(obj);
    SysBusDevice *dev = SYS_BUS_DEVICE(obj);

    sysbus_init_irq(dev, &s->irq);

    memory_region_init_io(&s->regs_region, obj, &tmu2_mmio_ops, s,
            "milkymist-tmu2", R_MAX * 4);
    sysbus_init_mmio(dev, &s->regs_region);
}

static void milkymist_tmu2_realize(DeviceState *dev, Error **errp)
{
    MilkymistTMU2State *s = MILKYMIST_TMU2(dev);

    if (tmu2_glx_init(s)) {
        error_setg(errp, "tmu2_glx_init failed");
    }
}

static const VMStateDescription vmstate_milkymist_tmu2 = {
    .name = "milkymist-tmu2",
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_UINT32_ARRAY(regs, MilkymistTMU2State, R_MAX),
        VMSTATE_END_OF_LIST()
    }
};

static void milkymist_tmu2_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);

    dc->realize = milkymist_tmu2_realize;
    dc->reset = milkymist_tmu2_reset;
    dc->vmsd = &vmstate_milkymist_tmu2;
}

static const TypeInfo milkymist_tmu2_info = {
    .name          = TYPE_MILKYMIST_TMU2,
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(MilkymistTMU2State),
    .instance_init = milkymist_tmu2_init,
    .class_init    = milkymist_tmu2_class_init,
};

static void milkymist_tmu2_register_types(void)
{
    type_register_static(&milkymist_tmu2_info);
}

type_init(milkymist_tmu2_register_types)

DeviceState *milkymist_tmu2_create(hwaddr base, qemu_irq irq)
{
    DeviceState *dev;
    Display *d;
    GLXFBConfig *configs;
    int nelements;
    int ver_major, ver_minor;

    /* check that GLX will work */
    d = XOpenDisplay(NULL);
    if (d == NULL) {
        return NULL;
    }

    if (!glXQueryVersion(d, &ver_major, &ver_minor)) {
        /*
         * Yeah, sometimes getting the GLX version can fail.
         * Isn't X beautiful?
         */
        XCloseDisplay(d);
        return NULL;
    }

    if ((ver_major < 1) || ((ver_major == 1) && (ver_minor < 3))) {
        printf("Your GLX version is %d.%d,"
          "but TMU emulation needs at least 1.3. TMU disabled.\n",
          ver_major, ver_minor);
        XCloseDisplay(d);
        return NULL;
    }

    configs = glXChooseFBConfig(d, 0, glx_fbconfig_attr, &nelements);
    if (configs == NULL) {
        XCloseDisplay(d);
        return NULL;
    }

    XFree(configs);
    XCloseDisplay(d);

    dev = qdev_create(NULL, TYPE_MILKYMIST_TMU2);
    qdev_init_nofail(dev);
    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);

    return dev;
}
