pikapython/package/Arm2D/arm_2d_rotation.c

938 lines
31 KiB
C
Raw Normal View History

2021-11-09 22:19:51 +08:00
/*
* Copyright (C) 2010-2020 Arm Limited or its affiliates. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* ----------------------------------------------------------------------
* Project: Arm-2D Library
* Title: arm-2d_rotation.c
* Description: APIs for tile rotation
*
* $Date: 29 April 2021
* $Revision: V.0.1.0
*
* Target Processor: Cortex-M cores
*
* -------------------------------------------------------------------- */
/*============================ INCLUDES ======================================*/
#define __ARM_2D_IMPL__
#include "arm_2d.h"
#include "__arm_2d_impl.h"
#include "math.h"
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-warning-option"
# pragma clang diagnostic ignored "-Wreserved-identifier"
# pragma clang diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers"
# pragma clang diagnostic ignored "-Wmissing-variable-declarations"
# pragma clang diagnostic ignored "-Wcast-qual"
# pragma clang diagnostic ignored "-Wcast-align"
# pragma clang diagnostic ignored "-Wextra-semi-stmt"
# pragma clang diagnostic ignored "-Wsign-conversion"
# pragma clang diagnostic ignored "-Wunused-function"
# pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"
# pragma clang diagnostic ignored "-Wdouble-promotion"
# pragma clang diagnostic ignored "-Wunused-parameter"
# pragma clang diagnostic ignored "-Wimplicit-float-conversion"
# pragma clang diagnostic ignored "-Wimplicit-int-conversion"
# pragma clang diagnostic ignored "-Wtautological-pointer-compare"
# pragma clang diagnostic ignored "-Wsign-compare"
# pragma clang diagnostic ignored "-Wfloat-conversion"
# pragma clang diagnostic ignored "-Wmissing-prototypes"
# pragma clang diagnostic ignored "-Wpadded"
# pragma clang diagnostic ignored "-Wundef"
#elif defined(__IS_COMPILER_ARM_COMPILER_5__)
# pragma diag_suppress 174,177,188,68,513,144
#elif defined(__IS_COMPILER_GCC__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
#endif
#include <arm_math.h>
/*============================ MACROS ========================================*/
#undef __PI
#define __PI 3.1415926f
#define __CALIB 0.009f
/* faster ATAN */
#define FAST_ATAN_F32_1(x, xabs) \
(x * (PI / 4.0f) + 0.273f * x * (1.0f - xabs))
#define EPS_ATAN2 1e-5f
/*----------------------------------------------------------------------------*
* Code Template *
*----------------------------------------------------------------------------*/
#define __API_PIXEL_AVERAGE_RESULT_GRAY8() \
( tPixel >> 8)
#define __API_PIXEL_AVERAGE_RESULT_RGB565() \
( tPixel.R >>= 8, \
tPixel.G >>= 8, \
tPixel.B >>= 8, \
__arm_2d_rgb565_pack(&tPixel));
#define __API_PIXEL_AVERAGE_RESULT_RGB888() \
( tPixel.R >>= 8, \
tPixel.G >>= 8, \
tPixel.B >>= 8, \
__arm_2d_cccn888_pack(&tPixel));
#define __API_COLOUR gray8
#define __API_INT_TYPE uint8_t
#define __API_PIXEL_AVERAGE_INIT() uint16_t tPixel = 0;
#define __API_PIXEL_BLENDING __ARM_2D_PIXEL_BLENDING_GRAY8
#define __API_PIXEL_AVERAGE __ARM_2D_PIXEL_AVERAGE_GRAY8
#define __API_PIXEL_AVERAGE_RESULT __API_PIXEL_AVERAGE_RESULT_GRAY8
#include "__arm_2d_rotate.inc"
#define __API_COLOUR rgb565
#define __API_INT_TYPE uint16_t
#define __API_PIXEL_BLENDING __ARM_2D_PIXEL_BLENDING_RGB565
#define __API_PIXEL_AVERAGE __ARM_2D_PIXEL_AVERAGE_RGB565
#define __API_PIXEL_AVERAGE_RESULT __API_PIXEL_AVERAGE_RESULT_RGB565
#include "__arm_2d_rotate.inc"
#define __API_COLOUR cccn888
#define __API_INT_TYPE uint32_t
#define __API_PIXEL_BLENDING __ARM_2D_PIXEL_BLENDING_CCCN888
#define __API_PIXEL_AVERAGE __ARM_2D_PIXEL_AVERAGE_CCCN888
#define __API_PIXEL_AVERAGE_RESULT __API_PIXEL_AVERAGE_RESULT_RGB888
#include "__arm_2d_rotate.inc"
/*============================ MACROFIED FUNCTIONS ===========================*/
/*============================ TYPES =========================================*/
/*============================ GLOBAL VARIABLES ==============================*/
/*============================ PROTOTYPES ====================================*/
/*============================ LOCAL VARIABLES ===============================*/
/*============================ IMPLEMENTATION ================================*/
#if __ARM_2D_CFG_FORCED_FIXED_POINT_ROTATION__
static
void __arm_2d_rotate_regression(arm_2d_size_t * __RESTRICT ptCopySize,
arm_2d_location_t * pSrcPoint,
float fAngle,
arm_2d_location_t * tOffset,
arm_2d_location_t * center,
arm_2d_rot_linear_regr_t regrCoefs[]
)
{
#define ONE_BY_2PI_Q31 341782637.0f
#define TO_Q16(x) ((x) << 16)
int_fast16_t iHeight = ptCopySize->iHeight;
int_fast16_t iWidth = ptCopySize->iWidth;
q31_t invHeightFx = 0x7fffffff / (iHeight - 1);
int32_t AngleFx = lroundf(fAngle * ONE_BY_2PI_Q31);
q31_t cosAngleFx = arm_cos_q31(AngleFx);
q31_t sinAngleFx = arm_sin_q31(AngleFx);
arm_2d_point_fx_t tPointCornerFx[2][2];
arm_2d_point_fx_t centerQ16;
arm_2d_point_fx_t srcPointQ16;
arm_2d_point_fx_t tOffsetQ16;
arm_2d_point_fx_t tmp;
int32_t iXQ16, iYQ16;
/* Q16 conversion */
centerQ16.X = TO_Q16(center->iX);
centerQ16.Y = TO_Q16(center->iY);
srcPointQ16.X = TO_Q16(pSrcPoint->iX);
srcPointQ16.Y = TO_Q16(pSrcPoint->iY);
tOffsetQ16.X = TO_Q16(tOffset->iX);
tOffsetQ16.Y = TO_Q16(tOffset->iY);
/* (0,0) corner */
tmp.X = srcPointQ16.X + 0 + tOffsetQ16.X;
tmp.Y = srcPointQ16.Y + 0 + tOffsetQ16.Y;
iXQ16 = tmp.X - centerQ16.X;
iYQ16 = tmp.Y - centerQ16.Y;
tPointCornerFx[0][0].Y =
__QDADD(__QDADD(centerQ16.Y, MULTFX(iYQ16, cosAngleFx)), MULTFX(iXQ16, sinAngleFx));
tPointCornerFx[0][0].X =
__QDSUB(__QDADD(centerQ16.X, MULTFX(iXQ16, cosAngleFx)), MULTFX(iYQ16, sinAngleFx));
/* ((iWidth - 1),0) corner */
tmp.X = srcPointQ16.X + 0 + tOffsetQ16.X + TO_Q16(iWidth - 1);
iXQ16 = tmp.X - centerQ16.X;
tPointCornerFx[1][0].Y =
__QDADD(__QDADD(centerQ16.Y, MULTFX(iYQ16, cosAngleFx)), MULTFX(iXQ16, sinAngleFx));
tPointCornerFx[1][0].X =
__QDSUB(__QDADD(centerQ16.X, MULTFX(iXQ16, cosAngleFx)), MULTFX(iYQ16, sinAngleFx));
/* ((iWidth - 1),(iHeight - 1)) corner */
tmp.Y = srcPointQ16.Y + tOffsetQ16.Y + TO_Q16(iHeight - 1);
iYQ16 = tmp.Y - centerQ16.Y;
tPointCornerFx[1][1].Y =
__QDADD(__QDADD(centerQ16.Y, MULTFX(iYQ16, cosAngleFx)), MULTFX(iXQ16, sinAngleFx));
tPointCornerFx[1][1].X =
__QDSUB(__QDADD(centerQ16.X, MULTFX(iXQ16, cosAngleFx)), MULTFX(iYQ16, sinAngleFx));
/* (0,(iHeight - 1)) corner */
tmp.X = srcPointQ16.X + 0 + tOffsetQ16.X;
iXQ16 = tmp.X - centerQ16.X;
tPointCornerFx[0][1].Y =
__QDADD(__QDADD(centerQ16.Y, MULTFX(iYQ16, cosAngleFx)), MULTFX(iXQ16, sinAngleFx));
tPointCornerFx[0][1].X =
__QDSUB(__QDADD(centerQ16.X, MULTFX(iXQ16, cosAngleFx)), MULTFX(iYQ16, sinAngleFx));
/* regression */
int32_t slopeXFx, slopeYFx;
/* interpolation in Y direction for 1st elements column */
slopeXFx = MULTFX((tPointCornerFx[0][1].X - tPointCornerFx[0][0].X), invHeightFx);
slopeYFx = MULTFX((tPointCornerFx[0][1].Y - tPointCornerFx[0][0].Y), invHeightFx);
regrCoefs[0].slopeY = slopeYFx * 2;
regrCoefs[0].slopeX = slopeXFx * 2;
regrCoefs[0].interceptY = tPointCornerFx[0][0].Y;
regrCoefs[0].interceptX = tPointCornerFx[0][0].X;
/* interpolation in Y direction for the last elements column */
slopeXFx = MULTFX((tPointCornerFx[1][1].X - tPointCornerFx[1][0].X), invHeightFx);
slopeYFx = MULTFX((tPointCornerFx[1][1].Y - tPointCornerFx[1][0].Y), invHeightFx);
regrCoefs[1].slopeY = slopeYFx* 2;
regrCoefs[1].slopeX = slopeXFx* 2;
regrCoefs[1].interceptY = tPointCornerFx[1][0].Y;
regrCoefs[1].interceptX = tPointCornerFx[1][0].X;
}
#else
static
void __arm_2d_rotate_regression(arm_2d_size_t * __RESTRICT ptCopySize,
arm_2d_location_t * pSrcPoint,
float fAngle,
arm_2d_location_t * tOffset,
arm_2d_location_t * ptCenter,
arm_2d_rot_linear_regr_t regrCoefs[])
{
int_fast16_t iHeight = ptCopySize->iHeight;
int_fast16_t iWidth = ptCopySize->iWidth;
float invHeight = 1.0f / (float) (iHeight - 1);
float cosAngle = arm_cos_f32(fAngle);
float sinAngle = arm_sin_f32(fAngle);
arm_2d_location_t tSrcPoint;
arm_2d_point_float_t tPointCorner[2][2];
int16_t iX, iY;
tSrcPoint.iX = pSrcPoint->iX + 0 + tOffset->iX;
tSrcPoint.iY = pSrcPoint->iY + 0 + tOffset->iY;
iX = tSrcPoint.iX - ptCenter->iX;
iY = tSrcPoint.iY - ptCenter->iY;
tPointCorner[0][0].fY = (iY * cosAngle + iX * sinAngle + ptCenter->iY);
tPointCorner[0][0].fX = (-iY * sinAngle + iX * cosAngle + ptCenter->iX);
tSrcPoint.iX = pSrcPoint->iX + (iWidth - 1) + tOffset->iX;
iX = tSrcPoint.iX - ptCenter->iX;
tPointCorner[1][0].fY = (iY * cosAngle + iX * sinAngle + ptCenter->iY);
tPointCorner[1][0].fX = (-iY * sinAngle + iX * cosAngle + ptCenter->iX);
tSrcPoint.iY = pSrcPoint->iY + (iHeight - 1) + tOffset->iY;
iY = tSrcPoint.iY - ptCenter->iY;
tPointCorner[1][1].fY = (iY * cosAngle + iX * sinAngle + ptCenter->iY);
tPointCorner[1][1].fX = (-iY * sinAngle + iX * cosAngle + ptCenter->iX);
tSrcPoint.iX = pSrcPoint->iX + 0 + tOffset->iX;
iX = tSrcPoint.iX - ptCenter->iX;
tPointCorner[0][1].fY = (iY * cosAngle + iX * sinAngle + ptCenter->iY);
tPointCorner[0][1].fX = (-iY * sinAngle + iX * cosAngle + ptCenter->iX);
float slopeX, slopeY;
/* interpolation in Y direction for 1st elements column */
slopeX = (tPointCorner[0][1].fX - tPointCorner[0][0].fX) * invHeight;
slopeY = (tPointCorner[0][1].fY - tPointCorner[0][0].fY) * invHeight;
regrCoefs[0].slopeY = slopeY;
regrCoefs[0].slopeX = slopeX;
regrCoefs[0].interceptY = tPointCorner[0][0].fY;
regrCoefs[0].interceptX = tPointCorner[0][0].fX;
/* interpolation in Y direction for the last elements column */
slopeX = (tPointCorner[1][1].fX - tPointCorner[1][0].fX) * invHeight;
slopeY = (tPointCorner[1][1].fY - tPointCorner[1][0].fY) * invHeight;
regrCoefs[1].slopeY = slopeY;
regrCoefs[1].slopeX = slopeX;
regrCoefs[1].interceptY = tPointCorner[1][0].fY;
regrCoefs[1].interceptX = tPointCorner[1][0].fX;
}
#endif
ARM_NONNULL(1,2,4)
static
arm_2d_point_float_t *__arm_2d_rotate_point(const arm_2d_location_t *ptLocation,
const arm_2d_location_t *ptCenter,
float fAngle,
arm_2d_point_float_t *ptOutBuffer)
{
int16_t iX = ptLocation->iX - ptCenter->iX;
int16_t iY = ptLocation->iY - ptCenter->iY;
float fX,fY;
float cosAngle = arm_cos_f32(fAngle);
float sinAngle = arm_sin_f32(fAngle);
fY = (iY * cosAngle + iX * sinAngle + ptCenter->iY);
fX = (-iY * sinAngle + iX * cosAngle + ptCenter->iX);
#if !defined(__ARM_2D_CFG_UNSAFE_IGNORE_CALIB_IN_ROTATION_FOR_PERFORMANCE__)
if (fX > 0) {
ptOutBuffer->fX = fX + __CALIB;
} else {
ptOutBuffer->fX = fX - __CALIB;
}
if (fY > 0) {
ptOutBuffer->fY = fY + __CALIB;
} else {
ptOutBuffer->fY = fY - __CALIB;
}
#else
ptOutBuffer->fX = fX;
ptOutBuffer->fY = fY;
#endif
return ptOutBuffer;
}
static arm_2d_err_t __arm_2d_rotate_preprocess_source(arm_2d_op_rotate_t *ptThis)
{
arm_2d_tile_t *ptSource = this.Source.ptTile;
memset(ptSource, 0, sizeof(*ptSource));
ptSource->tInfo = this.Origin.ptTile->tInfo;
ptSource->bIsRoot = true;
ptSource->pchBuffer = NULL; //!< special case
arm_2d_region_t tOrigValidRegion;
if (NULL == arm_2d_tile_get_root(this.Origin.ptTile, &tOrigValidRegion, NULL)) {
return ARM_2D_ERR_OUT_OF_REGION;
}
//! angle validation
this.tRotate.fAngle = fmodf(this.tRotate.fAngle, ARM_2D_ANGLE(360));
//! calculate the source region
do {
arm_2d_point_float_t tPoint;
arm_2d_location_t tTopLeft = {.iX = INT16_MAX, .iY = INT16_MAX};
arm_2d_location_t tBottomRight = {.iX = INT16_MIN, .iY = INT16_MIN};
//! Top Left
arm_2d_location_t tCornerPoint = tOrigValidRegion.tLocation;
__arm_2d_rotate_point( &tCornerPoint,
&this.tRotate.tCenter,
this.tRotate.fAngle,
&tPoint);
do {
tTopLeft.iX = MIN(tTopLeft.iX, tPoint.fX);
tTopLeft.iY = MIN(tTopLeft.iY, tPoint.fY);
tBottomRight.iX = MAX(tBottomRight.iX, tPoint.fX);
tBottomRight.iY = MAX(tBottomRight.iY, tPoint.fY);
} while(0);
//! Bottom Left
tCornerPoint.iY += tOrigValidRegion.tSize.iHeight - 1;
__arm_2d_rotate_point( &tCornerPoint,
&this.tRotate.tCenter,
this.tRotate.fAngle,
&tPoint);
do {
tTopLeft.iX = MIN(tTopLeft.iX, tPoint.fX);
tTopLeft.iY = MIN(tTopLeft.iY, tPoint.fY);
tBottomRight.iX = MAX(tBottomRight.iX, tPoint.fX);
tBottomRight.iY = MAX(tBottomRight.iY, tPoint.fY);
} while(0);
//! Top Right
tCornerPoint = tOrigValidRegion.tLocation;
tCornerPoint.iX += tOrigValidRegion.tSize.iWidth - 1;
__arm_2d_rotate_point( &tCornerPoint,
&this.tRotate.tCenter,
this.tRotate.fAngle,
&tPoint);
do {
tTopLeft.iX = MIN(tTopLeft.iX, tPoint.fX);
tTopLeft.iY = MIN(tTopLeft.iY, tPoint.fY);
tBottomRight.iX = MAX(tBottomRight.iX, tPoint.fX);
tBottomRight.iY = MAX(tBottomRight.iY, tPoint.fY);
} while(0);
//! Bottom Right
tCornerPoint.iY += tOrigValidRegion.tSize.iHeight - 1;
__arm_2d_rotate_point( &tCornerPoint,
&this.tRotate.tCenter,
this.tRotate.fAngle,
&tPoint);
do {
tTopLeft.iX = MIN(tTopLeft.iX, tPoint.fX);
tTopLeft.iY = MIN(tTopLeft.iY, tPoint.fY);
tBottomRight.iX = MAX(tBottomRight.iX, tPoint.fX);
tBottomRight.iY = MAX(tBottomRight.iY, tPoint.fY);
} while(0);
//! calculate the region
this.tRotate.tDummySourceOffset = tTopLeft;
ptSource->tRegion.tSize.iHeight = tBottomRight.iY - tTopLeft.iY + 1;
ptSource->tRegion.tSize.iWidth = tBottomRight.iX - tTopLeft.iX + 1;
//this.tRotate.tTargetRegion.tSize = ptSource->tRegion.tSize;
} while(0);
return ARM_2D_ERR_NONE;
}
static void __arm_2d_rotate_preprocess_target(
arm_2d_op_rotate_t *ptThis,
const arm_2d_location_t *ptTargetCentre)
{
this.tRotate.Target.tRegion.tSize = this.Source.ptTile->tRegion.tSize;
#if 0 //!< please keep this code for understanding the original meaning
arm_2d_region_t tTargetRegion = {0};
if (NULL != this.Target.ptRegion) {
tTargetRegion = *this.Target.ptRegion;
} else {
tTargetRegion.tSize = this.Target.ptTile->tRegion.tSize;
}
#else
//! equivalent code
assert(NULL == this.Target.ptRegion);
arm_2d_region_t tTargetRegion = {
.tSize = this.Target.ptTile->tRegion.tSize,
};
#endif
this.Target.ptRegion = &this.tRotate.Target.tRegion;
this.tRotate.Target.tRegion.tLocation = tTargetRegion.tLocation;
//! align with the specified center point
do {
arm_2d_location_t tOffset = {
.iX = this.tRotate.tCenter.iX - this.tRotate.tDummySourceOffset.iX,
.iY = this.tRotate.tCenter.iY - this.tRotate.tDummySourceOffset.iY,
};
if (NULL == ptTargetCentre) {
arm_2d_location_t tTargetCenter = {
.iX = tTargetRegion.tSize.iWidth >> 1,
.iY = tTargetRegion.tSize.iHeight >> 1,
};
tOffset.iX = tTargetCenter.iX - tOffset.iX;
tOffset.iY = tTargetCenter.iY - tOffset.iY;
} else {
tOffset.iX = ptTargetCentre->iX - tOffset.iX;
tOffset.iY = ptTargetCentre->iY - tOffset.iY;
}
this.tRotate.Target.tRegion.tLocation.iX += tOffset.iX;
this.tRotate.Target.tRegion.tLocation.iY += tOffset.iY;
} while(0);
}
ARM_NONNULL(2)
arm_2d_err_t arm_2dp_gray8_tile_rotation_prepare(
arm_2d_op_rotate_t *ptOP,
const arm_2d_tile_t *ptSource,
const arm_2d_location_t tCentre,
float fAngle,
uint8_t chFillColour)
{
assert(NULL != ptSource);
ARM_2D_IMPL(arm_2d_op_rotate_t, ptOP);
if (!arm_2d_op_wait_async((arm_2d_op_core_t *)ptThis)) {
return ARM_2D_ERR_BUSY;
}
OP_CORE.ptOp = &ARM_2D_OP_ROTATE_GRAY8;
this.Source.ptTile = &this.Origin.tDummySource;
this.Origin.ptTile = ptSource;
this.wMode = 0;
this.tRotate.fAngle = fAngle;
this.tRotate.tCenter = tCentre;
this.tRotate.Mask.hwColour = chFillColour;
return __arm_2d_rotate_preprocess_source(ptThis);
}
ARM_NONNULL(2)
arm_2d_err_t arm_2dp_rgb565_tile_rotation_prepare(
arm_2d_op_rotate_t *ptOP,
const arm_2d_tile_t *ptSource,
const arm_2d_location_t tCentre,
float fAngle,
uint16_t hwFillColour)
{
assert(NULL != ptSource);
ARM_2D_IMPL(arm_2d_op_rotate_t, ptOP);
if (!arm_2d_op_wait_async((arm_2d_op_core_t *)ptThis)) {
return ARM_2D_ERR_BUSY;
}
OP_CORE.ptOp = &ARM_2D_OP_ROTATE_RGB565;
this.Source.ptTile = &this.Origin.tDummySource;
this.Origin.ptTile = ptSource;
this.wMode = 0;
this.tRotate.fAngle = fAngle;
this.tRotate.tCenter = tCentre;
this.tRotate.Mask.hwColour = hwFillColour;
return __arm_2d_rotate_preprocess_source(ptThis);
}
ARM_NONNULL(2)
arm_2d_err_t arm_2dp_cccn888_tile_rotation_prepare(
arm_2d_op_rotate_t *ptOP,
const arm_2d_tile_t *ptSource,
const arm_2d_location_t tCentre,
float fAngle,
uint32_t wFillColour)
{
assert(NULL != ptSource);
ARM_2D_IMPL(arm_2d_op_rotate_t, ptOP);
if (!arm_2d_op_wait_async((arm_2d_op_core_t *)ptThis)) {
return ARM_2D_ERR_BUSY;
}
OP_CORE.ptOp = &ARM_2D_OP_ROTATE_RGB888;
this.Source.ptTile = &this.Origin.tDummySource;
this.Origin.ptTile = ptSource;
this.wMode = 0;
this.tRotate.fAngle = fAngle;
this.tRotate.tCenter = tCentre;
this.tRotate.Mask.hwColour = wFillColour;
return __arm_2d_rotate_preprocess_source(ptThis);
}
arm_fsm_rt_t __arm_2d_gray8_sw_rotate(__arm_2d_sub_task_t *ptTask)
{
ARM_2D_IMPL(arm_2d_op_rotate_t, ptTask->ptOP);
assert(ARM_2D_COLOUR_8BIT == OP_CORE.ptOp->Info.Colour.chScheme);
__arm_2d_impl_gray8_rotate(&(ptTask->Param.tCopyOrig),
&this.tRotate);
return arm_fsm_rt_cpl;
}
arm_fsm_rt_t __arm_2d_rgb565_sw_rotate(__arm_2d_sub_task_t *ptTask)
{
ARM_2D_IMPL(arm_2d_op_rotate_t, ptTask->ptOP);
assert(ARM_2D_COLOUR_RGB565 == OP_CORE.ptOp->Info.Colour.chScheme);
__arm_2d_impl_rgb565_rotate(&(ptTask->Param.tCopyOrig),
&this.tRotate);
return arm_fsm_rt_cpl;
}
arm_fsm_rt_t __arm_2d_cccn888_sw_rotate(__arm_2d_sub_task_t *ptTask)
{
ARM_2D_IMPL(arm_2d_op_rotate_t, ptTask->ptOP);
assert(ARM_2D_COLOUR_SZ_32BIT == OP_CORE.ptOp->Info.Colour.u3ColourSZ);
__arm_2d_impl_cccn888_rotate(&(ptTask->Param.tCopyOrig),
&this.tRotate);
return arm_fsm_rt_cpl;
}
ARM_NONNULL(2)
arm_2d_err_t arm_2dp_rgb565_tile_rotation_with_opacity_prepare(
arm_2d_op_rotate_opacity_t *ptOP,
const arm_2d_tile_t *ptSource,
const arm_2d_location_t tCentre,
float fAngle,
uint16_t hwFillColour,
uint_fast8_t chRatio)
{
assert(NULL != ptSource);
ARM_2D_IMPL(arm_2d_op_rotate_opacity_t, ptOP);
if (!arm_2d_op_wait_async((arm_2d_op_core_t *)ptThis)) {
return ARM_2D_ERR_BUSY;
}
OP_CORE.ptOp = &ARM_2D_OP_ROTATE_WITH_ALPHA_RGB565;
this.Source.ptTile = &this.Origin.tDummySource;
this.Origin.ptTile = ptSource;
this.wMode = 0;
this.tRotate.fAngle = fAngle;
this.tRotate.tCenter = tCentre;
this.tRotate.Mask.hwColour = hwFillColour;
this.chRatio = chRatio;
return __arm_2d_rotate_preprocess_source((arm_2d_op_rotate_t *)ptThis);
}
ARM_NONNULL(2)
arm_2d_err_t arm_2dp_cccn888_tile_rotation_with_opacity_prepare(
arm_2d_op_rotate_opacity_t *ptOP,
const arm_2d_tile_t *ptSource,
const arm_2d_location_t tCentre,
float fAngle,
uint32_t wFillColour,
uint_fast8_t chRatio)
{
assert(NULL != ptSource);
ARM_2D_IMPL(arm_2d_op_rotate_opacity_t, ptOP);
if (!arm_2d_op_wait_async((arm_2d_op_core_t *)ptThis)) {
return ARM_2D_ERR_BUSY;
}
OP_CORE.ptOp = &ARM_2D_OP_ROTATE_WITH_ALPHA_RGB888;
this.Source.ptTile = &this.Origin.tDummySource;
this.Origin.ptTile = ptSource;
this.wMode = 0;
this.tRotate.fAngle = fAngle;
this.tRotate.tCenter = tCentre;
this.tRotate.Mask.wColour = wFillColour;
this.chRatio = chRatio;
return __arm_2d_rotate_preprocess_source((arm_2d_op_rotate_t *)ptThis);
}
arm_fsm_rt_t __arm_2d_rgb565_sw_rotate_with_alpha(__arm_2d_sub_task_t *ptTask)
{
ARM_2D_IMPL(arm_2d_op_rotate_opacity_t, ptTask->ptOP);
assert(ARM_2D_COLOUR_RGB565 == OP_CORE.ptOp->Info.Colour.chScheme);
__arm_2d_impl_rgb565_rotate_alpha( &(ptTask->Param.tCopyOrig),
&this.tRotate,
this.chRatio);
return arm_fsm_rt_cpl;
}
arm_fsm_rt_t __arm_2d_cccn888_sw_rotate_with_alpha(__arm_2d_sub_task_t *ptTask)
{
ARM_2D_IMPL(arm_2d_op_rotate_opacity_t, ptTask->ptOP);
assert(ARM_2D_COLOUR_SZ_32BIT == OP_CORE.ptOp->Info.Colour.u3ColourSZ);
__arm_2d_impl_cccn888_rotate_alpha(&(ptTask->Param.tCopyOrig),
&this.tRotate,
this.chRatio);
return arm_fsm_rt_cpl;
}
ARM_NONNULL(2)
arm_fsm_rt_t arm_2dp_tile_rotate(arm_2d_op_rotate_t *ptOP,
const arm_2d_tile_t *ptTarget,
const arm_2d_region_t *ptRegion,
const arm_2d_location_t *ptTargetCentre)
{
assert(NULL != ptTarget);
ARM_2D_IMPL(arm_2d_op_rotate_t, ptOP);
arm_2d_location_t tTargetCentre;
if (!__arm_2d_op_acquire((arm_2d_op_core_t *)ptThis)) {
return arm_fsm_rt_on_going;
}
if (NULL != ptRegion) {
this.Target.ptTile = arm_2d_tile_generate_child(
ptTarget,
ptRegion,
&this.tRotate.Target.tTile,
false);
if (NULL == this.Target.ptTile) {
arm_fsm_rt_t tResult = (arm_fsm_rt_t)ARM_2D_ERR_OUT_OF_REGION;
if (ARM_2D_RUNTIME_FEATURE.TREAT_OUT_OF_RANGE_AS_COMPLETE) {
tResult = arm_fsm_rt_cpl;
}
return __arm_2d_op_depose((arm_2d_op_core_t *)ptThis, tResult);
}
if (NULL != ptTargetCentre) {
tTargetCentre.iX = ptTargetCentre->iX - ptRegion->tLocation.iX;
tTargetCentre.iY = ptTargetCentre->iY - ptRegion->tLocation.iY;
ptTargetCentre = &tTargetCentre;
}
} else {
this.Target.ptTile = ptTarget;
//this.Target.ptRegion = ptRegion;
}
this.Target.ptRegion = NULL;
__arm_2d_rotate_preprocess_target(ptThis, ptTargetCentre);
return __arm_2d_op_invoke((arm_2d_op_core_t *)ptThis);
}
/*----------------------------------------------------------------------------*
* Accelerable Low Level APIs *
*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*
* Draw a point whose cordinates is stored as float point. *
*----------------------------------------------------------------------------*/
#if 0
static arm_2d_region_t *__arm_2d_calculate_region( const arm_2d_point_float_t *ptLocation,
arm_2d_region_t *ptRegion)
{
assert(NULL != ptLocation);
assert(NULL != ptRegion);
/* +-----+-----+
* | P0 | P1 |
* +---- p ----+
* | P2 | -- |
* +-----+-----+
*/
arm_2d_location_t tPoints[3];
tPoints[0].iX = (int16_t)ptLocation->fX;
tPoints[2].iX = (int16_t)ptLocation->fX;
tPoints[1].iX = (int16_t)(ptLocation->fX + 0.99f);
ptRegion->tSize.iWidth = tPoints[1].iX - tPoints[0].iX + 1;
tPoints[0].iY = (int16_t)ptLocation->fY;
tPoints[2].iY = (int16_t)ptLocation->fY;
tPoints[1].iY = (int16_t)(ptLocation->fY + 0.99f);
ptRegion->tSize.iHeight = tPoints[2].iY - tPoints[0].iY + 1;
ptRegion->tLocation = tPoints[0];
return ptRegion;
}
#endif
/*----------------------------------------------------------------------------*
* Low Level IO Interfaces *
*----------------------------------------------------------------------------*/
__WEAK
def_low_lv_io(__ARM_2D_IO_ROTATE_GRAY8,
__arm_2d_gray8_sw_rotate);
__WEAK
def_low_lv_io(__ARM_2D_IO_ROTATE_RGB565,
__arm_2d_rgb565_sw_rotate);
__WEAK
def_low_lv_io(__ARM_2D_IO_ROTATE_RGB888,
__arm_2d_cccn888_sw_rotate);
__WEAK
def_low_lv_io(__ARM_2D_IO_ROTATE_WITH_ALPHA_RGB565,
__arm_2d_rgb565_sw_rotate_with_alpha);
__WEAK
def_low_lv_io(__ARM_2D_IO_ROTATE_WITH_ALPHA_RGB888,
__arm_2d_cccn888_sw_rotate_with_alpha);
const __arm_2d_op_info_t ARM_2D_OP_ROTATE_GRAY8 = {
.Info = {
.Colour = {
.chScheme = ARM_2D_COLOUR_8BIT,
},
.Param = {
.bHasSource = true,
.bHasOrigin = true,
.bHasTarget = true,
},
.chOpIndex = __ARM_2D_OP_IDX_ROTATE,
.LowLevelIO = {
.ptCopyOrigLike = ref_low_lv_io(__ARM_2D_IO_ROTATE_GRAY8),
.ptFillOrigLike = NULL,
},
},
};
const __arm_2d_op_info_t ARM_2D_OP_ROTATE_RGB565 = {
.Info = {
.Colour = {
.chScheme = ARM_2D_COLOUR_RGB565,
},
.Param = {
.bHasSource = true,
.bHasOrigin = true,
.bHasTarget = true,
},
.chOpIndex = __ARM_2D_OP_IDX_ROTATE,
.LowLevelIO = {
.ptCopyOrigLike = ref_low_lv_io(__ARM_2D_IO_ROTATE_RGB565),
.ptFillOrigLike = NULL,
},
},
};
const __arm_2d_op_info_t ARM_2D_OP_ROTATE_RGB888 = {
.Info = {
.Colour = {
.chScheme = ARM_2D_COLOUR_RGB888,
},
.Param = {
.bHasSource = true,
.bHasOrigin = true,
.bHasTarget = true,
},
.chOpIndex = __ARM_2D_OP_IDX_ROTATE,
.LowLevelIO = {
.ptCopyOrigLike = ref_low_lv_io(__ARM_2D_IO_ROTATE_RGB888),
.ptFillOrigLike = NULL,
},
},
};
const __arm_2d_op_info_t ARM_2D_OP_ROTATE_WITH_ALPHA_RGB565 = {
.Info = {
.Colour = {
.chScheme = ARM_2D_COLOUR_RGB565,
},
.Param = {
.bHasSource = true,
.bHasOrigin = true,
.bHasTarget = true,
},
.chOpIndex = __ARM_2D_OP_IDX_ROTATE_WITH_ALPHA,
.LowLevelIO = {
.ptCopyOrigLike = ref_low_lv_io(__ARM_2D_IO_ROTATE_WITH_ALPHA_RGB565),
.ptFillOrigLike = NULL,
},
},
};
const __arm_2d_op_info_t ARM_2D_OP_ROTATE_WITH_ALPHA_RGB888 = {
.Info = {
.Colour = {
.chScheme = ARM_2D_COLOUR_RGB888,
},
.Param = {
.bHasSource = true,
.bHasOrigin = true,
.bHasTarget = true,
},
.chOpIndex = __ARM_2D_OP_IDX_ROTATE_WITH_ALPHA,
.LowLevelIO = {
.ptCopyOrigLike = ref_low_lv_io(__ARM_2D_IO_ROTATE_WITH_ALPHA_RGB888),
.ptFillOrigLike = NULL,
},
},
};
#if defined(__clang__)
# pragma clang diagnostic pop
#elif defined(__IS_COMPILER_ARM_COMPILER_5__)
# pragma diag_warning 174,177,188,68,513,144
#elif defined(__IS_COMPILER_GCC__)
# pragma GCC diagnostic pop
#endif
#ifdef __cplusplus
}
#endif