/*************************************************************************
*
*   SDL_video.c
*
*   This module is currently a stubbed substitute for no_X_framebuffer.c
*   in the SDL client build.
*
*   $Id$
*
*   Copyright 2004-2012 Citrix Systems, Inc.  All Rights Reserved.
*
*************************************************************************/

#include "citrix.h"

#include <stdio.h>
#include <stdlib.h>

#include "SDL/SDL.h"

#include "mainloop.h"
#include "mlooplog.h"
#include "error.h"

/* Output window parameters. */

static SDL_Surface *surface;

/* Cache the screen and session dimensions. */

static struct {
    unsigned int screen_width, screen_height, screen_depth;
    unsigned int session_width, session_height;
} Dimensions;

/* Return size and depth for the display.
 * This is called during session initialisation, so the call to
 * SDL_GetVideoInfo() precedes any calls to SDL_SetVideoMode().
 *
 * Any subsequent calls should use cached values, as the result of
 * SDL_GetVideoInfo() is different after calling SDL_SetVideoMode()
 * and reflects the selected "window" size.
 */

void Get_max_screen_size(struct session_size *ssp)
{
    static BOOLEAN first_call = TRUE;

    const SDL_VideoInfo *SDLvip;
    int                  bpp;
 
   if (!first_call) {
        /* Not the initial call. */

        ssp->width =  Dimensions.screen_width;
        ssp->height = Dimensions.screen_height;
        ssp->depth =  Dimensions.screen_depth;
        return;
    }
    first_call = FALSE;

    SDLvip = SDL_GetVideoInfo();

    MLoopTrace("SDL_GetVideoInfo = %d x %d\n", SDLvip->current_w, SDLvip->current_h);

    /* Cache the screen resolution. */

    Dimensions.screen_width = ssp->width = SDLvip->current_w;
    Dimensions.screen_height = ssp->height = SDLvip->current_h;

    /* Guess maximum session depth.  But is this right?
     * A 15-bit session will probably look better on a 12-bit RGB display
     * than an 8-bit one.  And will SDL handle the conversion?
     * ***** TODO *****
     */

    bpp = SDLvip->vfmt->BitsPerPixel;
    if (bpp <= 8)
        ssp->depth = 8;
    else if (bpp < 24)
        ssp->depth = 16;
    else
        ssp->depth = 32;
    Dimensions.screen_depth = ssp->depth;
}

/* Set up the main window. */


/** SetupMainWindow
 * @param info - Thinwire session dimensions.
 */
BOOLEAN SetupMainWindow(struct session_size *info)
{
    if (info->depth > PXL_SIZE) {
        fprintf(stderr, "Bad session, aborting\n");
        exit(1);
    }

    MLoopTrace("Session size is %dx%d\n", info->width, info->height);
    Dimensions.session_width = info->width;
    Dimensions.session_height = info->height;

    /* Create "window". */

    surface = SDL_SetVideoMode(info->width, info->height, 0, 0);
    if (surface) {
#ifdef DEBUG
        SDL_PixelFormat *pfp;

        pfp = surface->format;
        MLoopTrace("Surface %dx%d flags %x bpp %d (%d;%d/%d;%d/%d;%d/%d;%d)"
                   " stride %d\n",
                   surface->w, surface->h, surface->flags,
                   pfp->BitsPerPixel,
                   8 - pfp->Rloss, pfp->Rshift,
                   8 - pfp->Gloss, pfp->Gshift,
                   8 - pfp->Bloss, pfp->Bshift,
                   8 - pfp->Aloss, pfp->Ashift,
                   surface->pitch);
#endif /* DEBUG */
    } else {
        fprintf(stderr, "Failed to create output window:%s\n",
                SDL_GetError());
        exit(1);
    }

    return TRUE;
}

/* Video output function.  This copies a rectangle of video data from
 * the LVB and makes it visible.  The rectangle is known to be valid.
 */

void SDL_draw_LVB(struct Draw_rect *rect, BOOLEAN flush)
{
    char       *ip, *op;
    UINT32      h, w;

    /* Copy the rectangle.  Pixels are assumed to be the same format. */

    ip = (char *)rect->pdata +
            (rect->y * rect->stride) + (rect->x * rect->bytes_per_pixel);
    op = (char *)surface->pixels +
             (rect->y * surface->pitch) +
             (rect->x * surface->format->BytesPerPixel);

    for (h = rect->height; h > 0; --h) {
        for (w = 0; w < rect->width; ++w)
            ((UINT32 *)op)[w] = ((UINT32 *)ip)[w] | 0xff000000; /* Set alpha */
        ip += rect->stride;
        op += surface->pitch;
    }

    /* I think this is what we are meant to do ... */

    SDL_UpdateRect(surface, rect->x, rect->y, rect->width, rect->height);
}
