/*
  Simple DirectMedia Layer
  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>

  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the authors be held liable for any damages
  arising from the use of this software.

  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely, subject to the following restrictions:

  1. The origin of this software must not be misrepresented; you must not
     claim that you wrote the original software. If you use this software
     in a product, an acknowledgment in the product documentation would be
     appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not be
     misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.
*/

#include "../../SDL_internal.h"

#if SDL_VIDEO_DRIVER_KMSDRM

#include "SDL_kmsdrmvideo.h"
#include "SDL_kmsdrmmouse.h"
#include "SDL_kmsdrmdyn.h"

#include "../../events/SDL_mouse_c.h"
#include "../../events/default_cursor.h"

static SDL_Cursor *KMSDRM_CreateDefaultCursor(void);
static SDL_Cursor *KMSDRM_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y);
static int KMSDRM_ShowCursor(SDL_Cursor * cursor);
static void KMSDRM_MoveCursor(SDL_Cursor * cursor);
static void KMSDRM_FreeCursor(SDL_Cursor * cursor);
static void KMSDRM_WarpMouse(SDL_Window * window, int x, int y);
static int KMSDRM_WarpMouseGlobal(int x, int y);

static SDL_Cursor *
KMSDRM_CreateDefaultCursor(void)
{
    return SDL_CreateCursor(default_cdata, default_cmask, DEFAULT_CWIDTH, DEFAULT_CHEIGHT, DEFAULT_CHOTX, DEFAULT_CHOTY);
}

/* Evaluate if a given cursor size is supported or not. Notably, current Intel gfx only support 64x64 and up. */
static SDL_bool
KMSDRM_IsCursorSizeSupported (int w, int h, uint32_t bo_format) {

    SDL_VideoDevice *dev = SDL_GetVideoDevice();
    SDL_VideoData *viddata = ((SDL_VideoData *)dev->driverdata);
    SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);

    int ret;
    uint32_t bo_handle;
    struct gbm_bo *bo = KMSDRM_gbm_bo_create(viddata->gbm, w, h, bo_format,
                                       GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);

    if (!bo) {
        SDL_SetError("Could not create GBM cursor BO width size %dx%d for size testing", w, h);
        goto cleanup;
    }

    bo_handle = KMSDRM_gbm_bo_get_handle(bo).u32;
    ret = KMSDRM_drmModeSetCursor(viddata->drm_fd, dispdata->crtc_id, bo_handle, w, h);

    if (ret) {
        goto cleanup;
    }
    else {
        KMSDRM_gbm_bo_destroy(bo);
        return SDL_TRUE;
    }

cleanup:
    if (bo) {
        KMSDRM_gbm_bo_destroy(bo);
    }
    return SDL_FALSE;
}

/* Create a cursor from a surface */
static SDL_Cursor *
KMSDRM_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
{
    SDL_VideoDevice *dev = SDL_GetVideoDevice();
    SDL_VideoData *viddata = ((SDL_VideoData *)dev->driverdata);
    SDL_PixelFormat *pixlfmt = surface->format;
    KMSDRM_CursorData *curdata;
    SDL_Cursor *cursor;
    SDL_bool cursor_supported = SDL_FALSE;
    int i, ret, usable_cursor_w, usable_cursor_h;
    uint32_t bo_format, bo_stride;
    char *buffer = NULL;
    size_t bufsize;

    switch(pixlfmt->format) {
    case SDL_PIXELFORMAT_RGB332:
        bo_format = GBM_FORMAT_RGB332;
        break;
    case SDL_PIXELFORMAT_ARGB4444:
        bo_format = GBM_FORMAT_ARGB4444;
        break;
    case SDL_PIXELFORMAT_RGBA4444:
        bo_format = GBM_FORMAT_RGBA4444;
        break;
    case SDL_PIXELFORMAT_ABGR4444:
        bo_format = GBM_FORMAT_ABGR4444;
        break;
    case SDL_PIXELFORMAT_BGRA4444:
        bo_format = GBM_FORMAT_BGRA4444;
        break;
    case SDL_PIXELFORMAT_ARGB1555:
        bo_format = GBM_FORMAT_ARGB1555;
        break;
    case SDL_PIXELFORMAT_RGBA5551:
        bo_format = GBM_FORMAT_RGBA5551;
        break;
    case SDL_PIXELFORMAT_ABGR1555:
        bo_format = GBM_FORMAT_ABGR1555;
        break;
    case SDL_PIXELFORMAT_BGRA5551:
        bo_format = GBM_FORMAT_BGRA5551;
        break;
    case SDL_PIXELFORMAT_RGB565:
        bo_format = GBM_FORMAT_RGB565;
        break;
    case SDL_PIXELFORMAT_BGR565:
        bo_format = GBM_FORMAT_BGR565;
        break;
    case SDL_PIXELFORMAT_RGB888:
    case SDL_PIXELFORMAT_RGB24:
        bo_format = GBM_FORMAT_RGB888;
        break;
    case SDL_PIXELFORMAT_BGR888:
    case SDL_PIXELFORMAT_BGR24:
        bo_format = GBM_FORMAT_BGR888;
        break;
    case SDL_PIXELFORMAT_RGBX8888:
        bo_format = GBM_FORMAT_RGBX8888;
        break;
    case SDL_PIXELFORMAT_BGRX8888:
        bo_format = GBM_FORMAT_BGRX8888;
        break;
    case SDL_PIXELFORMAT_ARGB8888:
        bo_format = GBM_FORMAT_ARGB8888;
        break;
    case SDL_PIXELFORMAT_RGBA8888:
        bo_format = GBM_FORMAT_RGBA8888;
        break;
    case SDL_PIXELFORMAT_ABGR8888:
        bo_format = GBM_FORMAT_ABGR8888;
        break;
    case SDL_PIXELFORMAT_BGRA8888:
        bo_format = GBM_FORMAT_BGRA8888;
        break;
    case SDL_PIXELFORMAT_ARGB2101010:
        bo_format = GBM_FORMAT_ARGB2101010;
        break;
    default:
        SDL_SetError("Unsupported pixel format for cursor");
        return NULL;
    }

    if (!KMSDRM_gbm_device_is_format_supported(viddata->gbm, bo_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE)) {
        SDL_SetError("Unsupported pixel format for cursor");
        return NULL;
    }

    cursor = (SDL_Cursor *) SDL_calloc(1, sizeof(*cursor));
    if (!cursor) {
        SDL_OutOfMemory();
        return NULL;
    }
    curdata = (KMSDRM_CursorData *) SDL_calloc(1, sizeof(*curdata));
    if (!curdata) {
        SDL_OutOfMemory();
        SDL_free(cursor);
        return NULL;
    }

    /* We have to know beforehand if a cursor with the same size as the surface is supported.
     * If it's not, we have to find an usable cursor size and use an intermediate and clean buffer.
     * If we can't find a cursor size supported by the hardware, we won't go on trying to 
     * call SDL_SetCursor() later. */

    usable_cursor_w = surface->w;
    usable_cursor_h = surface->h;

    while (usable_cursor_w <= MAX_CURSOR_W && usable_cursor_h <= MAX_CURSOR_H) { 
        if (KMSDRM_IsCursorSizeSupported(usable_cursor_w, usable_cursor_h, bo_format)) {
            cursor_supported = SDL_TRUE;
            break;
        }
        usable_cursor_w += usable_cursor_w;
        usable_cursor_h += usable_cursor_h;
    }

    if (!cursor_supported) {
        SDL_SetError("Could not find a cursor size supported by the kernel driver");
        goto cleanup;
    }

    curdata->hot_x = hot_x;
    curdata->hot_y = hot_y;
    curdata->w = usable_cursor_w;
    curdata->h = usable_cursor_h;

    curdata->bo = KMSDRM_gbm_bo_create(viddata->gbm, usable_cursor_w, usable_cursor_h, bo_format,
                                       GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);

    if (!curdata->bo) {
        SDL_SetError("Could not create GBM cursor BO");
        goto cleanup;
    }

    bo_stride = KMSDRM_gbm_bo_get_stride(curdata->bo);
    bufsize = bo_stride * curdata->h;

    if (surface->pitch != bo_stride) {
        /* pitch doesn't match stride, must be copied to temp buffer  */
        buffer = SDL_malloc(bufsize);
        if (!buffer) {
            SDL_OutOfMemory();
            goto cleanup;
        }

        if (SDL_MUSTLOCK(surface)) {
            if (SDL_LockSurface(surface) < 0) {
                /* Could not lock surface */
                goto cleanup;
            }
        }

        /* Clean the whole temporary buffer */
        SDL_memset(buffer, 0x00, bo_stride * curdata->h);

        /* Copy to temporary buffer */
        for (i = 0; i < surface->h; i++) {
            SDL_memcpy(buffer + (i * bo_stride),
                       ((char *)surface->pixels) + (i * surface->pitch),
                       surface->w * pixlfmt->BytesPerPixel);
        }

        if (SDL_MUSTLOCK(surface)) {
            SDL_UnlockSurface(surface);
        }

        if (KMSDRM_gbm_bo_write(curdata->bo, buffer, bufsize)) {
            SDL_SetError("Could not write to GBM cursor BO");
            goto cleanup;
        }

        /* Free temporary buffer */
        SDL_free(buffer);
        buffer = NULL;
    } else {
        /* surface matches BO format */
        if (SDL_MUSTLOCK(surface)) {
            if (SDL_LockSurface(surface) < 0) {
                /* Could not lock surface */
                goto cleanup;
            }
        }

        ret = KMSDRM_gbm_bo_write(curdata->bo, surface->pixels, bufsize);

        if (SDL_MUSTLOCK(surface)) {
            SDL_UnlockSurface(surface);
        }

        if (ret) {
            SDL_SetError("Could not write to GBM cursor BO");
            goto cleanup;
        }
    }

    cursor->driverdata = curdata;

    return cursor;

cleanup:
    if (buffer) {
        SDL_free(buffer);
    }
    if (cursor) {
        SDL_free(cursor);
    }
    if (curdata) {
        if (curdata->bo) {
            KMSDRM_gbm_bo_destroy(curdata->bo);
        }
        SDL_free(curdata);
    }
    return NULL;
}

/* Show the specified cursor, or hide if cursor is NULL */
static int
KMSDRM_ShowCursor(SDL_Cursor * cursor)
{
    SDL_VideoDevice *dev = SDL_GetVideoDevice();
    SDL_VideoData *viddata = ((SDL_VideoData *)dev->driverdata);
    SDL_Mouse *mouse;
    KMSDRM_CursorData *curdata;
    SDL_VideoDisplay *display = NULL;
    SDL_DisplayData *dispdata = NULL;
    int ret;
    uint32_t bo_handle;

    mouse = SDL_GetMouse();
    if (!mouse) {
        return SDL_SetError("No mouse.");
    }

    if (mouse->focus) {
        display = SDL_GetDisplayForWindow(mouse->focus);
        if (display) {
            dispdata = (SDL_DisplayData*) display->driverdata;
        }
    }

    if (!cursor) {
        /* Hide current cursor */
        if (mouse->cur_cursor && mouse->cur_cursor->driverdata) {
            curdata = (KMSDRM_CursorData *) mouse->cur_cursor->driverdata;

            if (curdata->crtc_id != 0) {
                ret = KMSDRM_drmModeSetCursor(viddata->drm_fd, curdata->crtc_id, 0, 0, 0);
                if (ret) {
                    SDL_SetError("Could not hide current cursor with drmModeSetCursor().");
                    return ret;
                }
                /* Mark previous cursor as not-displayed */
                curdata->crtc_id = 0;

                return 0;
            }
        }
        /* otherwise if possible, hide global cursor */
        if (dispdata && dispdata->crtc_id != 0) {
            ret = KMSDRM_drmModeSetCursor(viddata->drm_fd, dispdata->crtc_id, 0, 0, 0);
            if (ret) {
                SDL_SetError("Could not hide display's cursor with drmModeSetCursor().");
                return ret;
            }
            return 0;
        }

        return SDL_SetError("Couldn't find cursor to hide.");
    }
    /* If cursor != NULL, show new cursor on display */
    if (!display) {
        return SDL_SetError("Could not get display for mouse.");
    }
    if (!dispdata) {
        return SDL_SetError("Could not get display driverdata.");
    }

    curdata = (KMSDRM_CursorData *) cursor->driverdata;
    if (!curdata || !curdata->bo) {
        return SDL_SetError("Cursor not initialized properly.");
    }

    bo_handle = KMSDRM_gbm_bo_get_handle(curdata->bo).u32;
    if (curdata->hot_x == 0 && curdata->hot_y == 0) {
        ret = KMSDRM_drmModeSetCursor(viddata->drm_fd, dispdata->crtc_id, bo_handle,
                                      curdata->w, curdata->h);
    } else {
        ret = KMSDRM_drmModeSetCursor2(viddata->drm_fd, dispdata->crtc_id, bo_handle,
                                       curdata->w, curdata->h, curdata->hot_x, curdata->hot_y);
    }
    if (ret) {
        SDL_SetError("drmModeSetCursor failed.");
        return ret;
    }

    curdata->crtc_id = dispdata->crtc_id;

    return 0;
}

/* Free a window manager cursor */
static void
KMSDRM_FreeCursor(SDL_Cursor * cursor)
{
    KMSDRM_CursorData *curdata;
    int drm_fd;

    if (cursor) {
        curdata = (KMSDRM_CursorData *) cursor->driverdata;

        if (curdata) {
            if (curdata->bo) {
                if (curdata->crtc_id != 0) {
                    drm_fd = KMSDRM_gbm_device_get_fd(KMSDRM_gbm_bo_get_device(curdata->bo));
                    /* Hide the cursor if previously shown on a CRTC */
                    KMSDRM_drmModeSetCursor(drm_fd, curdata->crtc_id, 0, 0, 0);
                    curdata->crtc_id = 0;
                }
                KMSDRM_gbm_bo_destroy(curdata->bo);
                curdata->bo = NULL;
            }
            SDL_free(cursor->driverdata);
        }
        SDL_free(cursor);
    }
}

/* Warp the mouse to (x,y) */
static void
KMSDRM_WarpMouse(SDL_Window * window, int x, int y)
{
    /* Only one global/fullscreen window is supported */
    KMSDRM_WarpMouseGlobal(x, y);
}

/* Warp the mouse to (x,y) */
static int
KMSDRM_WarpMouseGlobal(int x, int y)
{
    KMSDRM_CursorData *curdata;
    SDL_Mouse *mouse = SDL_GetMouse();

    if (mouse && mouse->cur_cursor && mouse->cur_cursor->driverdata) {
        /* Update internal mouse position. */
        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 0, x, y);

        /* And now update the cursor graphic position on screen. */
        curdata = (KMSDRM_CursorData *) mouse->cur_cursor->driverdata;
        if (curdata->bo) {

            if (curdata->crtc_id != 0) {
                int ret, drm_fd;
                drm_fd = KMSDRM_gbm_device_get_fd(KMSDRM_gbm_bo_get_device(curdata->bo));
                ret = KMSDRM_drmModeMoveCursor(drm_fd, curdata->crtc_id, x, y);

                if (ret) {
                    SDL_SetError("drmModeMoveCursor() failed.");
                }

                return ret;
            } else {
                return SDL_SetError("Cursor is not currently shown.");
            }
        } else {
            return SDL_SetError("Cursor not initialized properly.");
        }
    } else {
        return SDL_SetError("No mouse or current cursor.");
    }
}

void
KMSDRM_InitMouse(_THIS)
{
    /* FIXME: Using UDEV it should be possible to scan all mice
     * but there's no point in doing so as there's no multimice support...yet!
     */
    SDL_Mouse *mouse = SDL_GetMouse();

    mouse->CreateCursor = KMSDRM_CreateCursor;
    mouse->ShowCursor = KMSDRM_ShowCursor;
    mouse->MoveCursor = KMSDRM_MoveCursor;
    mouse->FreeCursor = KMSDRM_FreeCursor;
    mouse->WarpMouse = KMSDRM_WarpMouse;
    mouse->WarpMouseGlobal = KMSDRM_WarpMouseGlobal;

    SDL_SetDefaultCursor(KMSDRM_CreateDefaultCursor());
}

void
KMSDRM_QuitMouse(_THIS)
{
    /* TODO: ? */
}

/* This is called when a mouse motion event occurs */
static void
KMSDRM_MoveCursor(SDL_Cursor * cursor)
{
    SDL_Mouse *mouse = SDL_GetMouse();
    KMSDRM_CursorData *curdata;
    int drm_fd, ret;

    /* We must NOT call SDL_SendMouseMotion() here or we will enter recursivity!
       That's why we move the cursor graphic ONLY. */
    if (mouse && mouse->cur_cursor && mouse->cur_cursor->driverdata) {
        curdata = (KMSDRM_CursorData *) mouse->cur_cursor->driverdata;
        drm_fd = KMSDRM_gbm_device_get_fd(KMSDRM_gbm_bo_get_device(curdata->bo));
        ret = KMSDRM_drmModeMoveCursor(drm_fd, curdata->crtc_id, mouse->x, mouse->y);

        if (ret) {
            SDL_SetError("drmModeMoveCursor() failed.");
        }
    }
}

#endif /* SDL_VIDEO_DRIVER_KMSDRM */

/* vi: set ts=4 sw=4 expandtab: */
