Logo Search packages:      
Sourcecode: linux-fsl-imx51 version File versions  Download package

rotate90_u16.c

/*
 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
 */

/*
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */

#include <linux/module.h>
#include "opl.h"

static int opl_rotate90_u16_by16(const u8 * src, int src_line_stride, int width,
                         int height, u8 * dst, int dst_line_stride,
                         int vmirror);
static int opl_rotate90_u16_by4(const u8 * src, int src_line_stride, int width,
                        int height, u8 * dst, int dst_line_stride,
                        int vmirror);
static int opl_rotate90_vmirror_u16_both(const u8 * src, int src_line_stride,
                               int width, int height, u8 * dst,
                               int dst_line_stride, int vmirror);
int opl_rotate90_u16_qcif(const u8 * src, u8 * dst);

00028 int opl_rotate90_u16(const u8 * src, int src_line_stride, int width, int height,
                 u8 * dst, int dst_line_stride)
{
      return opl_rotate90_vmirror_u16_both(src, src_line_stride, width,
                                  height, dst, dst_line_stride, 0);
}

00035 int opl_rotate90_vmirror_u16(const u8 * src, int src_line_stride, int width,
                      int height, u8 * dst, int dst_line_stride)
{
      return opl_rotate90_vmirror_u16_both(src, src_line_stride, width,
                                  height, dst, dst_line_stride, 1);
}

static int opl_rotate90_vmirror_u16_both(const u8 * src, int src_line_stride,
                               int width, int height, u8 * dst,
                               int dst_line_stride, int vmirror)
{
      const int BLOCK_SIZE_PIXELS = CACHE_LINE_WORDS * BYTES_PER_WORD
          / BYTES_PER_PIXEL;
      const int BLOCK_SIZE_PIXELS_BY4 = CACHE_LINE_WORDS * BYTES_PER_WORD
          / BYTES_PER_PIXEL / 4;

      if (!src || !dst)
            return OPLERR_NULL_PTR;

      if (width == 0 || height == 0 || src_line_stride == 0
          || dst_line_stride == 0)
            return OPLERR_BAD_ARG;

      /* The QCIF algorithm doesn't support vertical mirroring */
      if (vmirror == 0 && width == QCIF_Y_WIDTH && height == QCIF_Y_HEIGHT
          && src_line_stride == QCIF_Y_WIDTH * 2
          && src_line_stride == QCIF_Y_HEIGHT * 2)
            return opl_rotate90_u16_qcif(src, dst);
      else if (width % BLOCK_SIZE_PIXELS == 0
             && height % BLOCK_SIZE_PIXELS == 0)
            return opl_rotate90_u16_by16(src, src_line_stride, width,
                                   height, dst, dst_line_stride,
                                   vmirror);
      else if (width % BLOCK_SIZE_PIXELS_BY4 == 0
             && height % BLOCK_SIZE_PIXELS_BY4 == 0)
            return opl_rotate90_u16_by4(src, src_line_stride, width, height,
                                  dst, dst_line_stride, vmirror);
      else
            return OPLERR_BAD_ARG;
}

/*
 * Performs clockwise rotation (and possibly vertical mirroring depending
 * on the vmirror flag) using block sizes of 16x16
 * The algorithm is similar to 270 degree clockwise rotation algorithm
 */
static int opl_rotate90_u16_by16(const u8 * src, int src_line_stride, int width,
                         int height, u8 * dst, int dst_line_stride,
                         int vmirror)
{
      const int BLOCK_SIZE_PIXELS = CACHE_LINE_WORDS * BYTES_PER_WORD
          / BYTES_PER_PIXEL;
      const int BLOCK_SIZE_BYTES = BYTES_PER_PIXEL * BLOCK_SIZE_PIXELS;
      const int IN_INDEX = src_line_stride * BLOCK_SIZE_PIXELS
          + BYTES_PER_PIXEL;
      const int OUT_INDEX = vmirror ?
          -dst_line_stride - BLOCK_SIZE_BYTES
          : dst_line_stride - BLOCK_SIZE_BYTES;
      const u8 *in_block_ptr;
      u8 *out_block_ptr;
      int i, k;

      for (k = height / BLOCK_SIZE_PIXELS; k > 0; k--) {
            in_block_ptr = src + src_line_stride * (height - 1)
                - (src_line_stride * BLOCK_SIZE_PIXELS *
                   (height / BLOCK_SIZE_PIXELS - k));
            out_block_ptr = dst + BYTES_PER_PIXEL * BLOCK_SIZE_PIXELS *
                ((height / BLOCK_SIZE_PIXELS) - k);

            /*
             * For vertical mirroring the writing starts from the
             * bottom line
             */
            if (vmirror)
                  out_block_ptr += dst_line_stride * (width - 1);

            for (i = width; i > 0; i--) {
                  __asm__ volatile (
                        "ldrh r2, [%0], -%4\n\t"
                        "ldrh r3, [%0], -%4\n\t"
                        "ldrh r4, [%0], -%4\n\t"
                        "ldrh r5, [%0], -%4\n\t"
                        "orr  r2, r2, r3, lsl #16\n\t"
                        "orr  r4, r4, r5, lsl #16\n\t"
                        "str  r2, [%1], #4\n\t"
                        "str  r4, [%1], #4\n\t"

                        "ldrh r2, [%0], -%4\n\t"
                        "ldrh r3, [%0], -%4\n\t"
                        "ldrh r4, [%0], -%4\n\t"
                        "ldrh r5, [%0], -%4\n\t"
                        "orr  r2, r2, r3, lsl #16\n\t"
                        "orr  r4, r4, r5, lsl #16\n\t"
                        "str  r2, [%1], #4\n\t"
                        "str  r4, [%1], #4\n\t"

                        "ldrh r2, [%0], -%4\n\t"
                        "ldrh r3, [%0], -%4\n\t"
                        "ldrh r4, [%0], -%4\n\t"
                        "ldrh r5, [%0], -%4\n\t"
                        "orr  r2, r2, r3, lsl #16\n\t"
                        "orr  r4, r4, r5, lsl #16\n\t"
                        "str  r2, [%1], #4\n\t"
                        "str  r4, [%1], #4\n\t"

                        "ldrh r2, [%0], -%4\n\t"
                        "ldrh r3, [%0], -%4\n\t"
                        "ldrh r4, [%0], -%4\n\t"
                        "ldrh r5, [%0], -%4\n\t"
                        "orr  r2, r2, r3, lsl #16\n\t"
                        "orr  r4, r4, r5, lsl #16\n\t"
                        "str  r2, [%1], #4\n\t"
                        "str  r4, [%1], #4\n\t"

                        :"+r" (in_block_ptr), "+r"(out_block_ptr) /* output */
                        :"0"(in_block_ptr), "1"(out_block_ptr), "r"(src_line_stride)      /* input  */
                        :"r2", "r3", "r4", "r5", "memory"   /* modify */
                  );
                  in_block_ptr += IN_INDEX;
                  out_block_ptr += OUT_INDEX;
            }
      }

      return OPLERR_SUCCESS;
}

/*
 * Performs clockwise rotation (and possibly vertical mirroring depending
 * on the vmirror flag) using block sizes of 4x4
 * The algorithm is similar to 270 degree clockwise rotation algorithm
 */
static int opl_rotate90_u16_by4(const u8 * src, int src_line_stride, int width,
                        int height, u8 * dst, int dst_line_stride,
                        int vmirror)
{
      const int BLOCK_SIZE_PIXELS = CACHE_LINE_WORDS * BYTES_PER_WORD
          / BYTES_PER_PIXEL / 4;
      const int BLOCK_SIZE_BYTES = BYTES_PER_PIXEL * BLOCK_SIZE_PIXELS;
      const int IN_INDEX = src_line_stride * BLOCK_SIZE_PIXELS
          + BYTES_PER_PIXEL;
      const int OUT_INDEX = vmirror ?
          -dst_line_stride - BLOCK_SIZE_BYTES
          : dst_line_stride - BLOCK_SIZE_BYTES;
      const u8 *in_block_ptr;
      u8 *out_block_ptr;
      int i, k;

      for (k = height / BLOCK_SIZE_PIXELS; k > 0; k--) {
            in_block_ptr = src + src_line_stride * (height - 1)
                - (src_line_stride * BLOCK_SIZE_PIXELS *
                   (height / BLOCK_SIZE_PIXELS - k));
            out_block_ptr = dst + BYTES_PER_PIXEL * BLOCK_SIZE_PIXELS
                * ((height / BLOCK_SIZE_PIXELS) - k);

            /*
             * For horizontal mirroring the writing starts from the
             * bottom line
             */
            if (vmirror)
                  out_block_ptr += dst_line_stride * (width - 1);

            for (i = width; i > 0; i--) {
                  __asm__ volatile (
                        "ldrh r2, [%0], -%4\n\t"
                        "ldrh r3, [%0], -%4\n\t"
                        "ldrh r4, [%0], -%4\n\t"
                        "ldrh r5, [%0], -%4\n\t"
                        "orr  r2, r2, r3, lsl #16\n\t"
                        "orr  r4, r4, r5, lsl #16\n\t"
                        "str  r2, [%1], #4\n\t"
                        "str  r4, [%1], #4\n\t"

                        :"+r" (in_block_ptr), "+r"(out_block_ptr) /* output */
                        :"0"(in_block_ptr), "1"(out_block_ptr), "r"(src_line_stride)      /* input  */
                        :"r2", "r3", "r4", "r5", "memory"   /* modify */
                  );
                  in_block_ptr += IN_INDEX;
                  out_block_ptr += OUT_INDEX;
            }
      }

      return OPLERR_SUCCESS;
}

EXPORT_SYMBOL(opl_rotate90_u16);
EXPORT_SYMBOL(opl_rotate90_vmirror_u16);

Generated by  Doxygen 1.6.0   Back to index