/*
 * bgr_rgb16.c
 * Copyright (C) 2002 P.Everett <peter@everett9981.freeserve.co.uk>
 *
 * This file is part of KinoAMP, a free RISCOS MPEG program stream decoder.
 *
 * KinoAMP is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * KinoAMP 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*
 * This file contains the RGB output functions for 16bpp modes.
 */

#include <string.h>
#include "inttypes.h"
#include "ka_drawers.h"

/**
 * Converts an RGB source into a destination with 32K colours, 400% zoom.
 *
 * @param  paint  draw parameters
 */
void ka_drawbgr_z4_rgb16(const ka_paint_t* paint)
{
  int height;
  uint32_t *dst1, *dst2, *dst3, *dst4;
  const uint32_t *src;
  int dst_skip, src_skip;
  uint32_t rgb, rgb16;
  int i;


  height = paint->yc_height;
  dst1 = (uint32_t*) paint->dst;   // 1 row screen address
  dst2 = dst1 + paint->dst_bpr/4;  // 2 row screen address
  dst3 = dst2 + paint->dst_bpr/4;  // 3 row screen address
  dst4 = dst3 + paint->dst_bpr/4;  // 4 row screen address
  src = (uint32_t*) paint->base.y; // source address

  dst_skip = (3*paint->dst_bpr + paint->dst_skip) >> 2;
  src_skip = (paint->yc_skip >> 2);

  do
  {
    i = paint->yc_width;
    do
    {
      rgb = *src++;
      rgb16  = (rgb & 0xf80000) >> 17;
      rgb16 |= (rgb & 0x00fc00) >> 5;
      rgb16 |= (rgb & 0x0000f8) << 6;
      rgb16 |= rgb16 << 16;
      *dst1++ = rgb16;
      *dst1++ = rgb16;
      *dst2++ = rgb16;
      *dst2++ = rgb16;
      *dst3++ = rgb16;
      *dst3++ = rgb16;
      *dst4++ = rgb16;
      *dst4++ = rgb16;
    }
    while(--i);

    src  += src_skip;
    dst1 += dst_skip;
    dst2 += dst_skip;
    dst3 += dst_skip;
    dst4 += dst_skip;
  }
  while(--height);
}

/**
 * Converts an RGB source into a destination with 32K colours, 300% zoom.
 *
 * @param  paint  draw parameters
 */
void ka_drawbgr_z3_rgb16(const ka_paint_t* paint)
{
  int height;
  uint32_t *dst1, *dst2, *dst3;
  const uint32_t *src;
  int dst_skip, src_skip;
  uint32_t rgb, rgb16;
  int i;

  height = paint->yc_height;
  dst1 = (uint32_t*) paint->dst;   // 1 row screen address
  dst2 = dst1 + paint->dst_bpr/4;  // 2 row screen address
  dst3 = dst2 + paint->dst_bpr/4;  // 3 row screen address
  src = (uint32_t*) paint->base.y; // source address

  dst_skip = (2*paint->dst_bpr + paint->dst_skip) >> 2;
  src_skip = (paint->yc_skip >> 2);

  do
  {
    i = (paint->yc_width >> 1);
    do
    {
      rgb = *src++;
      rgb16  = (rgb & 0xf80000) >> 17;
      rgb16 |= (rgb & 0x00fc00) >> 5;
      rgb16 |= (rgb & 0x0000f8) << 6;
      rgb16 |= rgb16 << 16;
      *dst1++ = rgb16;
      *dst2++ = rgb16;
      *dst3++ = rgb16;
      rgb = *src++;
      rgb16 <<= 16;
      rgb16 |= (rgb & 0xf80000) >> 17;
      rgb16 |= (rgb & 0x00fc00) >> 5;
      rgb16 |= (rgb & 0x0000f8) << 6;
      *dst1++ = rgb16;
      *dst2++ = rgb16;
      *dst3++ = rgb16;
      rgb16 <<= 16;
      rgb16 |= rgb16 >> 16;
      *dst1++ = rgb16;
      *dst2++ = rgb16;
      *dst3++ = rgb16;
    }
    while(--i);

    src  += src_skip;
    dst1 += dst_skip;
    dst2 += dst_skip;
    dst3 += dst_skip;
  }
  while(--height);
}

/**
 * Converts an RGB source into a destination with 32K colours, 200% zoom.
 *
 * @param  paint  draw parameters
 */
void ka_drawbgr_z2_rgb16(const ka_paint_t* paint)
{
  int height;
  uint32_t *dst1, *dst2;
  const uint32_t *src;
  int dst_skip, src_skip;
  uint32_t rgb, rgb16;
  int i;

  height = paint->yc_height;
  dst1 = (uint32_t*) paint->dst;   // 1 row screen address
  dst2 = dst1 + paint->dst_bpr/4;  // 2 row screen address
  src = (uint32_t*) paint->base.y; // source address

  dst_skip = (paint->dst_bpr + paint->dst_skip) >> 2;
  src_skip = (paint->yc_skip >> 2);

  do
  {
    i = paint->yc_width;
    do
    {
      rgb = *src++;
      rgb16  = (rgb & 0xf80000) >> 17;
      rgb16 |= (rgb & 0x00fc00) >> 5;
      rgb16 |= (rgb & 0x0000f8) << 6;
      rgb16 |= rgb16 << 16;
      *dst1++ = rgb16;
      *dst2++ = rgb16;
    }
    while(--i);

    src  += src_skip;
    dst1 += dst_skip;
    dst2 += dst_skip;
  }
  while(--height);
}

/**
 * Converts an RGB source into a destination with 32K colours, 100% zoom.
 *
 * @param  paint  draw parameters
 */
void ka_drawbgr_z1_rgb16(const ka_paint_t* paint)
{
  int height;
  uint32_t *dst;
  const uint32_t *src;
  int dst_skip, src_skip;
  uint32_t rgb, rgb16;
  int i;


  height = paint->yc_height;
  dst = (uint32_t*) paint->dst;    // screen address
  src = (uint32_t*) paint->base.y; // source address

  dst_skip = (paint->dst_skip >> 2);
  src_skip = (paint->yc_skip >> 2);

  do
  {
    i = (paint->yc_width >> 1);
    do
    {
      rgb = *src++;
      rgb16  = (rgb & 0xf80000) >> 17;
      rgb16 |= (rgb & 0x00fc00) >> 5;
      rgb16 |= (rgb & 0x0000f8) << 6;
      rgb = *src++;
      rgb16 |= (rgb & 0xf80000) >>  1;
      rgb16 |= (rgb & 0x00fc00) << 11;
      rgb16 |= (rgb & 0x0000f8) << 22;
      *dst++ = rgb16;
    }
    while(--i);

    src += src_skip;
    dst += dst_skip;
  }
  while(--height);
}

/**
 * Converts an RGB source into a destination with 32K colours, 50% zoom.
 *
 * @param  paint  draw parameters
 */
void ka_drawbgr_z05_rgb16(const ka_paint_t* paint)
{
  int height;
  uint32_t* dst;
  const uint32_t* src;
  int dst_skip, src_skip;
  uint32_t rgb, rgb16;
  int i;

  height = paint->yc_height >> 1;
  dst = (uint32_t*) paint->dst;    // screen address
  src = (uint32_t*) paint->base.y; // source address

  dst_skip = (paint->dst_skip) >> 2;
  src_skip = (paint->yc_bpr + paint->yc_skip) >> 2;

  do
  {
    i = (paint->yc_width >> 2);
    do
    {
      rgb = *src;
      src += 2;
      rgb16  = (rgb & 0xf80000) >> 17;
      rgb16 |= (rgb & 0x00fc00) >> 5;
      rgb16 |= (rgb & 0x0000f8) << 6;
      rgb = *src;
      src += 2;
      rgb16 |= (rgb & 0xf80000) >>  1;
      rgb16 |= (rgb & 0x00fc00) << 11;
      rgb16 |= (rgb & 0x0000f8) << 22;
      *dst++ = rgb16;
    }
    while(--i);

    src += src_skip;
    dst += dst_skip;
  }
  while(--height);
}
