mirror of
https://gitee.com/Lyon1998/pikapython.git
synced 2025-01-15 17:02:53 +08:00
1514 lines
57 KiB
C
1514 lines
57 KiB
C
/*
|
|
* Copyright (C) 2010-2021 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_core.c
|
|
* Description: Basic Tile operations
|
|
*
|
|
* $Date: 02. Oct 2021
|
|
* $Revision: V.0.9.0
|
|
*
|
|
* Target Processor: Cortex-M cores
|
|
*
|
|
* -------------------------------------------------------------------- */
|
|
|
|
|
|
/*============================ INCLUDES ======================================*/
|
|
|
|
#if defined(__clang__)
|
|
# pragma clang diagnostic ignored "-Wempty-translation-unit"
|
|
#endif
|
|
|
|
#ifdef __ARM_2D_COMPILATION_UNIT
|
|
|
|
|
|
#define __ARM_2D_IMPL__
|
|
|
|
#include "arm_2d.h"
|
|
#include "__arm_2d_impl.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 "-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 "-Wmissing-prototypes"
|
|
# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
|
|
# pragma clang diagnostic ignored "-Wgnu-statement-expression"
|
|
# pragma clang diagnostic ignored "-Wswitch-enum"
|
|
# pragma clang diagnostic ignored "-Wswitch"
|
|
#elif defined(__IS_COMPILER_ARM_COMPILER_5__)
|
|
# pragma diag_suppress 174,177,188,68,513
|
|
#elif defined(__IS_COMPILER_GCC__)
|
|
# pragma GCC diagnostic push
|
|
# pragma GCC diagnostic ignored "-Wenum-compare"
|
|
# pragma GCC diagnostic ignored "-Wpedantic"
|
|
# pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
|
#endif
|
|
|
|
/*============================ MACROS ========================================*/
|
|
#ifndef __ARM_2D_DEFAULT_SUB_TASK_POOL_SIZE
|
|
# define __ARM_2D_DEFAULT_SUB_TASK_POOL_SIZE 3
|
|
#endif
|
|
|
|
/*============================ MACROFIED FUNCTIONS ===========================*/
|
|
/*============================ TYPES =========================================*/
|
|
/*============================ GLOBAL VARIABLES ==============================*/
|
|
|
|
__WEAK
|
|
arm_2d_runtime_feature_t ARM_2D_RUNTIME_FEATURE = {
|
|
.TREAT_OUT_OF_RANGE_AS_COMPLETE = 1,
|
|
.HAS_DEDICATED_THREAD_FOR_2D_TASK = 0,
|
|
};
|
|
/*============================ PROTOTYPES ====================================*/
|
|
/*============================ LOCAL VARIABLES ===============================*/
|
|
/*============================ IMPLEMENTATION ================================*/
|
|
|
|
ARM_NOINIT
|
|
struct __arm_2d_op_control ARM_2D_CTRL;
|
|
|
|
#define __arm_2d_get_address_and_region_from_tile( __TILE_PTR, \
|
|
__VALID_REGION_NAME, \
|
|
__LOCATION_OFFSET_PTR, \
|
|
__TYPE, \
|
|
__BUF_PTR_NAME) \
|
|
arm_2d_region_t __VALID_REGION_NAME; \
|
|
assert(NULL != (__TILE_PTR)); \
|
|
__TYPE *(__BUF_PTR_NAME) = NULL; \
|
|
\
|
|
(__TILE_PTR) = arm_2d_tile_get_root((__TILE_PTR), \
|
|
&__VALID_REGION_NAME, \
|
|
__LOCATION_OFFSET_PTR); \
|
|
\
|
|
if (NULL != (__TILE_PTR)) { \
|
|
(__BUF_PTR_NAME) = ((__TYPE *)((__TILE_PTR)->pchBuffer)) \
|
|
+ (__TILE_PTR)->tRegion.tSize.iWidth * \
|
|
__VALID_REGION_NAME.tLocation.iY \
|
|
+ __VALID_REGION_NAME.tLocation.iX; \
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------*
|
|
* Region Calculation *
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
__WEAK
|
|
arm_fsm_rt_t __arm_2d_issue_sub_task_tile_process(
|
|
arm_2d_op_t *ptThis,
|
|
__arm_2d_tile_param_t *ptParam)
|
|
{
|
|
arm_fsm_rt_t tResult = (arm_fsm_rt_t)ARM_2D_ERR_NOT_SUPPORT;
|
|
__arm_2d_sub_task_t *ptTask = &(__arm_2d_sub_task_t){
|
|
.ptOP = (arm_2d_op_core_t *)ptThis,
|
|
.Param.tTileProcess = *ptParam,
|
|
};
|
|
|
|
/* todo: update the tile process interface */
|
|
|
|
/* call default software implementation */
|
|
ARM_2D_RUN_DEFAULT( 0, __arm_2d_io_func_t);
|
|
return tResult;
|
|
}
|
|
|
|
|
|
__WEAK
|
|
arm_fsm_rt_t __arm_2d_issue_sub_task_fill(
|
|
arm_2d_op_cp_t *ptThis,
|
|
__arm_2d_tile_param_t *ptSource,
|
|
__arm_2d_tile_param_t *ptTarget)
|
|
{
|
|
arm_fsm_rt_t tResult = (arm_fsm_rt_t)ARM_2D_ERR_NOT_SUPPORT;
|
|
|
|
__arm_2d_sub_task_t *ptTask = &(__arm_2d_sub_task_t){
|
|
.ptOP = (arm_2d_op_core_t *)ptThis,
|
|
.Param.tFill = {
|
|
.tSource = *ptSource,
|
|
.tTarget = *ptTarget,
|
|
},
|
|
};
|
|
|
|
/* call default software implementation */
|
|
ARM_2D_RUN_DEFAULT( 1,__arm_2d_io_func_t );
|
|
|
|
return tResult;
|
|
}
|
|
|
|
__WEAK
|
|
arm_fsm_rt_t __arm_2d_issue_sub_task_fill_with_mask(
|
|
arm_2d_op_cp_t *ptThis,
|
|
__arm_2d_tile_param_t *ptSource,
|
|
__arm_2d_tile_param_t *ptSourceMask,
|
|
__arm_2d_tile_param_t *ptTarget,
|
|
__arm_2d_tile_param_t *ptTargetMask)
|
|
{
|
|
arm_fsm_rt_t tResult = (arm_fsm_rt_t)ARM_2D_ERR_NOT_SUPPORT;
|
|
|
|
__arm_2d_sub_task_t *ptTask = &(__arm_2d_sub_task_t){
|
|
.ptOP = (arm_2d_op_core_t *)ptThis,
|
|
.Param.tFillMask = {
|
|
.use_as____arm_2d_param_fill_t = {
|
|
.tSource = *ptSource,
|
|
.tTarget = *ptTarget,
|
|
},
|
|
},
|
|
};
|
|
|
|
if (NULL == ptSourceMask){
|
|
ptTask->Param.tFillMask.tSrcMask.bInvalid = true;
|
|
} else {
|
|
ptTask->Param.tFillMask.tSrcMask = *ptSourceMask;
|
|
}
|
|
|
|
if (NULL == ptTargetMask){
|
|
ptTask->Param.tFillMask.tDesMask.bInvalid = true;
|
|
} else {
|
|
ptTask->Param.tFillMask.tDesMask = *ptTargetMask;
|
|
}
|
|
|
|
/* call default software implementation */
|
|
ARM_2D_RUN_DEFAULT( 1,__arm_2d_io_func_t );
|
|
|
|
return tResult;
|
|
}
|
|
|
|
__WEAK
|
|
arm_fsm_rt_t __arm_2d_issue_sub_task_copy(arm_2d_op_cp_t *ptThis,
|
|
__arm_2d_tile_param_t *ptSource,
|
|
__arm_2d_tile_param_t *ptTarget,
|
|
arm_2d_size_t * __RESTRICT ptCopySize)
|
|
{
|
|
arm_fsm_rt_t tResult = (arm_fsm_rt_t)ARM_2D_ERR_NOT_SUPPORT;
|
|
__arm_2d_sub_task_t *ptTask = &(__arm_2d_sub_task_t){
|
|
.ptOP = (arm_2d_op_core_t *)ptThis,
|
|
.Param.tCopy = {
|
|
.tSource = *ptSource,
|
|
.tTarget = *ptTarget,
|
|
.tCopySize = *ptCopySize,
|
|
},
|
|
};
|
|
|
|
/* call default software implementation */
|
|
ARM_2D_RUN_DEFAULT(0,__arm_2d_io_func_t );
|
|
|
|
return tResult;
|
|
}
|
|
|
|
__WEAK
|
|
arm_fsm_rt_t __arm_2d_issue_sub_task_copy_with_mask(
|
|
arm_2d_op_cp_t *ptThis,
|
|
__arm_2d_tile_param_t *ptSource,
|
|
__arm_2d_tile_param_t *ptSourceMask,
|
|
__arm_2d_tile_param_t *ptTarget,
|
|
__arm_2d_tile_param_t *ptTargetMask,
|
|
arm_2d_size_t * __RESTRICT ptCopySize)
|
|
{
|
|
arm_fsm_rt_t tResult = (arm_fsm_rt_t)ARM_2D_ERR_NOT_SUPPORT;
|
|
__arm_2d_sub_task_t *ptTask = &(__arm_2d_sub_task_t){
|
|
.ptOP = (arm_2d_op_core_t *)ptThis,
|
|
.Param.tCopyMask = {
|
|
.use_as____arm_2d_param_copy_t = {
|
|
.tSource = *ptSource,
|
|
.tTarget = *ptTarget,
|
|
.tCopySize = *ptCopySize,
|
|
},
|
|
},
|
|
};
|
|
|
|
if (NULL == ptSourceMask){
|
|
ptTask->Param.tCopyMask.tSrcMask.bInvalid = true;
|
|
} else {
|
|
ptTask->Param.tCopyMask.tSrcMask = *ptSourceMask;
|
|
}
|
|
|
|
if (NULL == ptTargetMask){
|
|
ptTask->Param.tCopyMask.tDesMask.bInvalid = true;
|
|
} else {
|
|
ptTask->Param.tCopyMask.tDesMask = *ptTargetMask;
|
|
}
|
|
|
|
/* call default software implementation */
|
|
ARM_2D_RUN_DEFAULT(0,__arm_2d_io_func_t );
|
|
|
|
return tResult;
|
|
}
|
|
|
|
__WEAK
|
|
arm_fsm_rt_t __arm_2d_issue_sub_task_fill_origin(
|
|
arm_2d_op_cp_t *ptThis,
|
|
__arm_2d_tile_param_t *ptSource,
|
|
__arm_2d_tile_param_t *ptOrigin,
|
|
__arm_2d_tile_param_t *ptTarget)
|
|
{
|
|
arm_fsm_rt_t tResult = (arm_fsm_rt_t)ARM_2D_ERR_NOT_SUPPORT;
|
|
|
|
|
|
__arm_2d_sub_task_t *ptTask = &(__arm_2d_sub_task_t){
|
|
.ptOP = (arm_2d_op_core_t *)ptThis,
|
|
.Param.tFillOrig = {
|
|
.use_as____arm_2d_param_fill_t = {
|
|
.tSource = *ptSource,
|
|
.tTarget = *ptTarget,
|
|
},
|
|
.tOrigin = *ptOrigin,
|
|
},
|
|
};
|
|
|
|
/* call default software implementation */
|
|
ARM_2D_RUN_DEFAULT( 1,__arm_2d_io_func_t );
|
|
|
|
return tResult;
|
|
}
|
|
|
|
__WEAK
|
|
arm_fsm_rt_t __arm_2d_issue_sub_task_copy_origin(
|
|
arm_2d_op_cp_t *ptThis,
|
|
__arm_2d_tile_param_t *ptSource,
|
|
__arm_2d_tile_param_t *ptOrigin,
|
|
__arm_2d_tile_param_t *ptTarget,
|
|
arm_2d_size_t * __RESTRICT ptCopySize)
|
|
{
|
|
arm_fsm_rt_t tResult = (arm_fsm_rt_t)ARM_2D_ERR_NOT_SUPPORT;
|
|
__arm_2d_sub_task_t *ptTask = &(__arm_2d_sub_task_t){
|
|
.ptOP = (arm_2d_op_core_t *)ptThis,
|
|
.Param.tCopyOrig = {
|
|
.use_as____arm_2d_param_copy_t = {
|
|
.tSource = *ptSource,
|
|
.tTarget = *ptTarget,
|
|
.tCopySize = *ptCopySize,
|
|
},
|
|
.tOrigin = *ptOrigin,
|
|
},
|
|
};
|
|
|
|
/* call default software implementation */
|
|
ARM_2D_RUN_DEFAULT(0,__arm_2d_io_func_t );
|
|
|
|
return tResult;
|
|
}
|
|
|
|
|
|
|
|
ARM_NONNULL(1,2)
|
|
static const arm_2d_tile_t * __arm_2d_tile_region_caculator(
|
|
const arm_2d_tile_t *ptTile,
|
|
__arm_2d_tile_param_t *ptOut,
|
|
uint_fast8_t *pchPixelLenInBit,
|
|
bool bAllowEnforcedColour,
|
|
uint32_t wMode)
|
|
{
|
|
arm_2d_region_t tValidRegion;
|
|
int32_t nOffset = 0;
|
|
uint8_t *pchBuffer = NULL;
|
|
|
|
assert(NULL != ptTile);
|
|
assert(NULL != ptOut);
|
|
|
|
bool bDerivedResource = ptTile->tInfo.bDerivedResource
|
|
& !ptTile->tInfo.bIsRoot;
|
|
|
|
|
|
//memset(ptOut, 0, sizeof(__arm_2d_tile_param_t));
|
|
|
|
ptTile = arm_2d_tile_get_root( ptTile,
|
|
&tValidRegion,
|
|
NULL);
|
|
|
|
if (NULL != ptTile) {
|
|
|
|
//! check if enforced colour is allowed
|
|
if (bAllowEnforcedColour) {
|
|
if (ptTile->tInfo.bHasEnforcedColour) {
|
|
*pchPixelLenInBit = _BV(ptTile->tInfo.tColourInfo.u3ColourSZ);
|
|
}
|
|
}
|
|
|
|
uint_fast8_t chPixelLenInBit = *pchPixelLenInBit;
|
|
|
|
arm_2d_location_t tOffset = tValidRegion.tLocation;
|
|
if ((wMode) & ARM_2D_CP_MODE_X_MIRROR) {
|
|
tOffset.iX = 0;
|
|
}
|
|
if ((wMode) & ARM_2D_CP_MODE_Y_MIRROR) {
|
|
tOffset.iY = 0;
|
|
}
|
|
|
|
if (chPixelLenInBit >= 8) {
|
|
nOffset = ptTile->tRegion.tSize.iWidth * tOffset.iY + tOffset.iX;
|
|
pchBuffer = ptTile->pchBuffer
|
|
+ (nOffset * chPixelLenInBit >> 3);
|
|
} else {
|
|
|
|
nOffset = tOffset.iX;
|
|
|
|
pchBuffer = ptTile->pchBuffer
|
|
+ ((ptTile->tRegion.tSize.iWidth
|
|
* chPixelLenInBit + 7) >> 3) * tOffset.iY
|
|
+ ((tOffset.iX * chPixelLenInBit) >> 3);
|
|
}
|
|
|
|
ptOut->iStride = ptTile->tRegion.tSize.iWidth;
|
|
ptOut->nOffset = nOffset;
|
|
ptOut->pBuffer = pchBuffer;
|
|
ptOut->tValidRegion = tValidRegion;
|
|
ptOut->tColour.chScheme = ptTile->tColourInfo.chScheme;
|
|
ptOut->bDerivedResource = bDerivedResource;
|
|
ptOut->bInvalid = false;
|
|
}
|
|
|
|
return ptTile;
|
|
}
|
|
|
|
|
|
ARM_NONNULL(1,2)
|
|
static
|
|
arm_fsm_rt_t __arm_2d_tile_process( arm_2d_op_t *ptThis,
|
|
const arm_2d_tile_t *ptTarget)
|
|
{
|
|
assert(NULL != ptTarget);
|
|
assert(OP_CORE.ptOp->Info.Colour.u3ColourSZ >= ARM_2D_COLOUR_SZ_8BIT);
|
|
|
|
arm_fsm_rt_t tResult = (arm_fsm_rt_t)ARM_2D_ERR_NOT_SUPPORT;
|
|
|
|
uint_fast8_t chPixelLenInBit = _BV(OP_CORE.ptOp->Info.Colour.u3ColourSZ);
|
|
|
|
__arm_2d_tile_param_t tTileParam;
|
|
__arm_2d_tile_region_caculator(
|
|
ptTarget,
|
|
&tTileParam,
|
|
&chPixelLenInBit,
|
|
OP_CORE.ptOp->Info.Param.bAllowEnforcedColour,
|
|
0);
|
|
|
|
tResult = __arm_2d_issue_sub_task_tile_process( ptThis, &tTileParam);
|
|
|
|
return tResult;
|
|
}
|
|
|
|
|
|
static void __arm_2d_source_side_tile_mirror_preprocess(
|
|
const arm_2d_tile_t *ptTile,
|
|
__arm_2d_tile_param_t *ptTileParam,
|
|
uint_fast8_t chPixelLenInBit,
|
|
const arm_2d_size_t *ptActualSize,
|
|
uint32_t wMode)
|
|
{
|
|
//! right and/or bottom alignment
|
|
arm_2d_size_t tOffset = {0};
|
|
|
|
if (ptTileParam->bDerivedResource) {
|
|
//!< treat the content inside the valid region as the one to be mirrored
|
|
//! right alignment
|
|
if (wMode & ARM_2D_CP_MODE_X_MIRROR) {
|
|
tOffset.iWidth = ptTileParam->tValidRegion.tLocation.iX;
|
|
tOffset.iWidth += ptTileParam->tValidRegion.tSize.iWidth
|
|
- ptActualSize->iWidth;
|
|
}
|
|
|
|
//! bottom alignment
|
|
if (wMode & ARM_2D_CP_MODE_Y_MIRROR) {
|
|
tOffset.iHeight = ptTileParam->tValidRegion.tLocation.iY;
|
|
tOffset.iHeight += ptTileParam->tValidRegion.tSize.iHeight
|
|
- ptActualSize->iHeight;
|
|
}
|
|
} else {
|
|
|
|
//!< treat valid region as a logic region to indicate the area for mirroring.
|
|
//! right alignment
|
|
if (wMode & ARM_2D_CP_MODE_X_MIRROR) {
|
|
tOffset.iWidth = ptTile->tRegion.tSize.iWidth
|
|
- ( ptTileParam->tValidRegion.tLocation.iX
|
|
+ ptActualSize->iWidth);
|
|
}
|
|
|
|
//! bottom alignment
|
|
if (wMode & ARM_2D_CP_MODE_Y_MIRROR) {
|
|
tOffset.iHeight = ptTile->tRegion.tSize.iHeight
|
|
- ( ptTileParam->tValidRegion.tLocation.iY
|
|
+ ptActualSize->iHeight);
|
|
}
|
|
}
|
|
|
|
if (chPixelLenInBit >= 8) {
|
|
|
|
ptTileParam->nOffset += ( tOffset.iHeight * ptTile->tRegion.tSize.iWidth
|
|
+ tOffset.iWidth);
|
|
|
|
ptTileParam->pBuffer = ptTile->pchBuffer
|
|
+ (ptTileParam->nOffset * chPixelLenInBit >> 3);
|
|
} else {
|
|
ptTileParam->nOffset += tOffset.iWidth;
|
|
|
|
(*(uintptr_t *)&(ptTileParam->pBuffer)) +=
|
|
+ ((ptTile->tRegion.tSize.iWidth
|
|
* chPixelLenInBit + 7) >> 3) * tOffset.iHeight
|
|
+ ((tOffset.iWidth * chPixelLenInBit) >> 3);
|
|
}
|
|
}
|
|
|
|
ARM_NONNULL(1,2)
|
|
static
|
|
arm_fsm_rt_t __arm_2d_big_pixel_tile_pave( arm_2d_op_cp_t *ptThis,
|
|
const arm_2d_tile_t *ptSource,
|
|
const arm_2d_tile_t *ptSourceMask,
|
|
const arm_2d_tile_t *ptTarget,
|
|
const arm_2d_tile_t *ptTargetMask,
|
|
uint32_t wMode)
|
|
{
|
|
assert(NULL != ptSource);
|
|
assert(NULL != ptTarget);
|
|
//assert(OP_CORE.ptOp->Info.Colour.u3ColourSZ >= ARM_2D_COLOUR_SZ_8BIT);
|
|
|
|
arm_fsm_rt_t tResult = (arm_fsm_rt_t)ARM_2D_ERR_NOT_SUPPORT;
|
|
uint_fast8_t chTargetPixelLenInBit = _BV(OP_CORE.ptOp->Info.Colour.u3ColourSZ);
|
|
uint_fast8_t chSourcePixelLenInBit = chTargetPixelLenInBit;
|
|
uint_fast8_t chSourceMaskPixelLenInBit = 8;
|
|
|
|
__arm_2d_tile_param_t tSourceTileParam;
|
|
__arm_2d_tile_param_t tSourceMaskParam;
|
|
__arm_2d_tile_param_t tTargetTileParam;
|
|
__arm_2d_tile_param_t tTargetMaskParam;
|
|
__arm_2d_tile_param_t tOriginTileParam;
|
|
arm_2d_tile_t tSourceMask;
|
|
arm_2d_tile_t tTargetMask;
|
|
|
|
//const arm_2d_tile_t *ptTargetMask = NULL;
|
|
//const arm_2d_tile_t *ptSourceMask = NULL;
|
|
|
|
const arm_2d_tile_t *ptOrigin = NULL;
|
|
|
|
if (OP_CORE.ptOp->Info.Param.bHasOrigin) {
|
|
arm_2d_op_src_orig_t *ptOP = (arm_2d_op_src_orig_t *)ptThis;
|
|
uint_fast8_t chOriginPixelLenInBit = chSourcePixelLenInBit;
|
|
ptOrigin = __arm_2d_tile_region_caculator(
|
|
ptOP->Origin.ptTile,
|
|
&tOriginTileParam,
|
|
&chOriginPixelLenInBit,
|
|
OP_CORE.ptOp->Info.Param.bAllowEnforcedColour,
|
|
wMode);
|
|
|
|
if (NULL == ptOrigin) {
|
|
return (arm_fsm_rt_t)ARM_2D_ERR_OUT_OF_REGION;
|
|
}
|
|
}
|
|
|
|
ptSource = __arm_2d_tile_region_caculator(
|
|
ptSource,
|
|
&tSourceTileParam,
|
|
&chSourcePixelLenInBit,
|
|
OP_CORE.ptOp->Info.Param.bAllowEnforcedColour,
|
|
wMode);
|
|
|
|
|
|
|
|
ptTarget = __arm_2d_tile_region_caculator(
|
|
ptTarget,
|
|
&tTargetTileParam,
|
|
&chTargetPixelLenInBit,
|
|
false,
|
|
0);
|
|
|
|
if (NULL == ptSource || NULL == ptTarget) {
|
|
return (arm_fsm_rt_t)ARM_2D_ERR_OUT_OF_REGION;
|
|
}
|
|
|
|
|
|
if (!OP_CORE.ptOp->Info.Param.bHasOrigin) {
|
|
if (OP_CORE.ptOp->Info.Param.bHasSrcMask) {
|
|
arm_2d_op_src_msk_t *ptOP = (arm_2d_op_src_msk_t *)ptThis;
|
|
|
|
ptSourceMask = ptOP->Mask.ptSourceSide;
|
|
|
|
if (NULL != ptSourceMask) {
|
|
ptSourceMask = arm_2d_tile_generate_child( ptSourceMask,
|
|
&tSourceTileParam.tValidRegion,
|
|
&tSourceMask,
|
|
false);
|
|
|
|
ptSourceMask = __arm_2d_tile_region_caculator(
|
|
ptSourceMask,
|
|
&tSourceMaskParam,
|
|
&chSourceMaskPixelLenInBit,
|
|
true,
|
|
wMode);
|
|
}
|
|
}
|
|
|
|
if (OP_CORE.ptOp->Info.Param.bHasDesMask) {
|
|
arm_2d_op_src_msk_t *ptOP = (arm_2d_op_src_msk_t *)ptThis;
|
|
ptTargetMask = ptOP->Mask.ptTargetSide;
|
|
if (NULL != ptTargetMask) {
|
|
uint_fast8_t chTargetMaskPixelLenInBit = 8;
|
|
|
|
do {
|
|
arm_2d_region_t tTempRegion= {
|
|
.tSize = ptThis->Target.ptTile->tRegion.tSize,
|
|
};
|
|
|
|
arm_2d_get_absolute_location(ptThis->Target.ptTile,
|
|
&tTempRegion.tLocation);
|
|
|
|
tTempRegion.tLocation.iX
|
|
= tTargetTileParam.tValidRegion.tLocation.iX
|
|
- tTempRegion.tLocation.iX;
|
|
|
|
|
|
|
|
tTempRegion.tSize.iWidth
|
|
= tTargetTileParam.tValidRegion.tSize.iWidth
|
|
- tTempRegion.tSize.iWidth;
|
|
|
|
#if 0 //! no use for now
|
|
tTempRegion.tLocation.iY
|
|
= tTargetTileParam.tValidRegion.tLocation.iY
|
|
- tTempRegion.tLocation.iY;
|
|
|
|
tTempRegion.tSize.iHeight
|
|
= tTargetTileParam.tValidRegion.tSize.iHeight
|
|
- tTempRegion.tSize.iHeight;
|
|
#endif
|
|
|
|
arm_2d_region_t tNewTargetMaskRegion = ptTargetMask->tRegion;
|
|
|
|
tNewTargetMaskRegion.tLocation.iX += tTempRegion.tLocation.iX;
|
|
tNewTargetMaskRegion.tSize.iWidth += tTempRegion.tSize.iWidth;
|
|
|
|
|
|
ptTargetMask = arm_2d_tile_generate_child(
|
|
ptTargetMask,
|
|
&tNewTargetMaskRegion,
|
|
&tTargetMask,
|
|
false);
|
|
|
|
} while(0);
|
|
|
|
|
|
ptTargetMask = __arm_2d_tile_region_caculator(
|
|
ptTargetMask,
|
|
&tTargetMaskParam,
|
|
&chTargetMaskPixelLenInBit,
|
|
true,
|
|
0);
|
|
}
|
|
}
|
|
} //!else { //! todo }
|
|
|
|
if (wMode & ARM_2D_CP_MODE_FILL) {
|
|
|
|
//! handle mirroring
|
|
do {
|
|
__arm_2d_source_side_tile_mirror_preprocess(
|
|
ptSource,
|
|
&tSourceTileParam,
|
|
chSourcePixelLenInBit,
|
|
&tSourceTileParam.tValidRegion.tSize,
|
|
wMode);
|
|
|
|
if ( OP_CORE.ptOp->Info.Param.bHasSrcMask
|
|
&& (NULL != ptSourceMask)) {
|
|
__arm_2d_source_side_tile_mirror_preprocess(
|
|
ptSourceMask,
|
|
&tSourceMaskParam,
|
|
chSourceMaskPixelLenInBit,
|
|
&tSourceMaskParam.tValidRegion.tSize,
|
|
wMode);
|
|
}
|
|
} while(0);
|
|
|
|
if (OP_CORE.ptOp->Info.Param.bHasOrigin) {
|
|
tResult = __arm_2d_issue_sub_task_fill_origin(
|
|
ptThis,
|
|
&tSourceTileParam,
|
|
&tOriginTileParam,
|
|
&tTargetTileParam);
|
|
} else {
|
|
if ( (OP_CORE.ptOp->Info.Param.bHasSrcMask)
|
|
|| (OP_CORE.ptOp->Info.Param.bHasDesMask)){
|
|
|
|
tResult = __arm_2d_issue_sub_task_fill_with_mask(
|
|
ptThis,
|
|
&tSourceTileParam,
|
|
((NULL != ptSourceMask) ? &tSourceMaskParam : NULL),
|
|
&tTargetTileParam,
|
|
((NULL != ptTargetMask) ? &tTargetMaskParam : NULL)
|
|
);
|
|
} else {
|
|
tResult = __arm_2d_issue_sub_task_fill( ptThis,
|
|
&tSourceTileParam,
|
|
&tTargetTileParam);
|
|
}
|
|
}
|
|
} else {
|
|
arm_2d_size_t tActualSize = {
|
|
.iWidth = MIN( tSourceTileParam.tValidRegion.tSize.iWidth,
|
|
tTargetTileParam.tValidRegion.tSize.iWidth),
|
|
.iHeight = MIN( tSourceTileParam.tValidRegion.tSize.iHeight,
|
|
tTargetTileParam.tValidRegion.tSize.iHeight),
|
|
};
|
|
|
|
//! handle mirroring
|
|
do {
|
|
__arm_2d_source_side_tile_mirror_preprocess(
|
|
ptSource,
|
|
&tSourceTileParam,
|
|
chSourcePixelLenInBit,
|
|
&tActualSize,
|
|
wMode);
|
|
|
|
if ( OP_CORE.ptOp->Info.Param.bHasSrcMask
|
|
&& (NULL != ptSourceMask)) {
|
|
arm_2d_size_t tMaskActualSize = {
|
|
.iWidth = MIN(tActualSize.iWidth,
|
|
tSourceMaskParam.tValidRegion.tSize.iWidth),
|
|
.iHeight = MIN(tActualSize.iHeight,
|
|
tSourceMaskParam.tValidRegion.tSize.iHeight),
|
|
};
|
|
__arm_2d_source_side_tile_mirror_preprocess(
|
|
ptSourceMask,
|
|
&tSourceMaskParam,
|
|
chSourceMaskPixelLenInBit,
|
|
&tMaskActualSize,
|
|
wMode);
|
|
}
|
|
} while(0);
|
|
|
|
if (OP_CORE.ptOp->Info.Param.bHasOrigin) {
|
|
|
|
tResult = __arm_2d_issue_sub_task_copy_origin( ptThis,
|
|
&tSourceTileParam,
|
|
&tOriginTileParam,
|
|
&tTargetTileParam,
|
|
&tActualSize);
|
|
} else {
|
|
|
|
if ( (OP_CORE.ptOp->Info.Param.bHasSrcMask)
|
|
|| (OP_CORE.ptOp->Info.Param.bHasDesMask)){
|
|
tResult = __arm_2d_issue_sub_task_copy_with_mask(
|
|
ptThis,
|
|
&tSourceTileParam,
|
|
((NULL != ptSourceMask) ? &tSourceMaskParam : NULL),
|
|
&tTargetTileParam,
|
|
((NULL != ptTargetMask) ? &tTargetMaskParam : NULL),
|
|
&tActualSize);
|
|
} else {
|
|
tResult = __arm_2d_issue_sub_task_copy( ptThis,
|
|
&tSourceTileParam,
|
|
&tTargetTileParam,
|
|
&tActualSize);
|
|
}
|
|
}
|
|
}
|
|
|
|
return tResult;
|
|
}
|
|
|
|
|
|
static
|
|
arm_fsm_rt_t __tile_clipped_pave(
|
|
arm_2d_op_cp_t *ptThis,
|
|
const arm_2d_tile_t *ptTarget,
|
|
const arm_2d_region_t *ptRegion,
|
|
arm_2d_region_t *ptClippedRegion,
|
|
uint32_t wMode)
|
|
{
|
|
|
|
arm_2d_tile_t tTempSourceTile = {0};
|
|
arm_2d_tile_t tTargetTile = {0};
|
|
|
|
arm_fsm_rt_t tResult = (arm_fsm_rt_t)ARM_2D_ERR_OUT_OF_REGION;
|
|
do {
|
|
arm_2d_region_t tempRegion = {
|
|
.tLocation = this.Source.ptTile->tRegion.tLocation,
|
|
.tSize = ptRegion->tSize,
|
|
};
|
|
|
|
tempRegion.tLocation.iX = -ptRegion->tLocation.iX;
|
|
tempRegion.tLocation.iY = -ptRegion->tLocation.iY;
|
|
tempRegion.tSize.iWidth += ptRegion->tLocation.iX;
|
|
tempRegion.tSize.iHeight += ptRegion->tLocation.iY;
|
|
|
|
|
|
if (NULL == arm_2d_tile_generate_child( this.Source.ptTile,
|
|
&tempRegion,
|
|
&tTempSourceTile,
|
|
true)) {
|
|
break;
|
|
};
|
|
|
|
if (NULL != ptClippedRegion) {
|
|
*ptClippedRegion = tTempSourceTile.tRegion;
|
|
}
|
|
|
|
//! [Modify][Target.ptTile]
|
|
//if (NULL == arm_2d_tile_generate_child( this.Target.ptTile,
|
|
if (NULL == arm_2d_tile_generate_child( //this.use_as__arm_2d_op_core_t.Runtime.ptTargetTile,
|
|
ptTarget,
|
|
ptRegion,
|
|
&tTargetTile,
|
|
true)) {
|
|
break;
|
|
}
|
|
|
|
|
|
#if 0
|
|
switch (OP_CORE.ptOp->Info.Colour.u3ColourSZ) {
|
|
case ARM_2D_COLOUR_SZ_8BIT:
|
|
case ARM_2D_COLOUR_SZ_16BIT:
|
|
case ARM_2D_COLOUR_SZ_32BIT:
|
|
tResult = __arm_2d_big_pixel_tile_pave( ptThis,
|
|
&tTempSourceTile,
|
|
&tTargetTile,
|
|
wMode);
|
|
break;
|
|
default:
|
|
tResult = (arm_fsm_rt_t)ARM_2D_ERR_NOT_SUPPORT;
|
|
break;
|
|
}
|
|
#else
|
|
if (OP_CORE.ptOp->Info.Colour.u3ColourSZ >= ARM_2D_COLOUR_SZ_8BIT) {
|
|
tResult = __arm_2d_big_pixel_tile_pave( ptThis,
|
|
&tTempSourceTile,
|
|
NULL, //!< source mask
|
|
&tTargetTile,
|
|
NULL, //!< target mask
|
|
wMode);
|
|
} else {
|
|
tResult = (arm_fsm_rt_t)ARM_2D_ERR_NOT_SUPPORT;
|
|
}
|
|
#endif
|
|
} while(0);
|
|
|
|
return tResult;
|
|
}
|
|
|
|
static arm_fsm_rt_t __tile_non_negtive_location_pave(
|
|
arm_2d_op_cp_t *ptThis,
|
|
const arm_2d_tile_t *ptSource,
|
|
const arm_2d_tile_t *ptTarget,
|
|
const arm_2d_region_t *ptRegion,
|
|
uint32_t wMode)
|
|
{
|
|
arm_fsm_rt_t tResult = (arm_fsm_rt_t)ARM_2D_ERR_OUT_OF_REGION;
|
|
do {
|
|
arm_2d_tile_t tTile = {0};
|
|
if (NULL == arm_2d_tile_generate_child(ptTarget, ptRegion, &tTile, true)) {
|
|
break;
|
|
}
|
|
#if 0
|
|
switch (OP_CORE.ptOp->Info.Colour.u3ColourSZ) {
|
|
case ARM_2D_COLOUR_SZ_8BIT:
|
|
case ARM_2D_COLOUR_SZ_16BIT:
|
|
case ARM_2D_COLOUR_SZ_32BIT:
|
|
tResult = __arm_2d_big_pixel_tile_pave(ptThis, ptSource, &tTile, wMode);
|
|
break;
|
|
default:
|
|
tResult = (arm_fsm_rt_t)ARM_2D_ERR_NOT_SUPPORT;
|
|
break;
|
|
}
|
|
#else
|
|
if (OP_CORE.ptOp->Info.Colour.u3ColourSZ >= ARM_2D_COLOUR_SZ_8BIT) {
|
|
tResult = __arm_2d_big_pixel_tile_pave( ptThis,
|
|
ptSource,
|
|
NULL, //!< source mask
|
|
&tTile,
|
|
NULL, //!< target mask
|
|
wMode);
|
|
} else {
|
|
tResult = (arm_fsm_rt_t)ARM_2D_ERR_NOT_SUPPORT;
|
|
}
|
|
#endif
|
|
} while(0);
|
|
|
|
return tResult;
|
|
}
|
|
|
|
|
|
__WEAK
|
|
bool __arm_2d_op_ensure_resource( arm_2d_op_core_t *ptOP,
|
|
uint_fast16_t hwRequired)
|
|
{
|
|
ARM_2D_UNUSED(hwRequired);
|
|
ARM_2D_UNUSED(ptOP);
|
|
return true;
|
|
}
|
|
|
|
static
|
|
arm_fsm_rt_t __arm_2d_op_frontend_region_process( arm_2d_op_core_t *ptOP)
|
|
{
|
|
ARM_2D_IMPL(arm_2d_op_t, ptOP)
|
|
|
|
arm_fsm_rt_t tResult = (arm_fsm_rt_t)ARM_2D_ERR_OUT_OF_REGION;;
|
|
arm_2d_tile_t tTile = {0};
|
|
arm_2d_region_t tDrawRegion = {0};
|
|
arm_2d_region_t tTargetRegion = {0};
|
|
arm_2d_tile_t *ptTarget = NULL;
|
|
|
|
if (!__arm_2d_op_ensure_resource(ptOP, 1)) {
|
|
//! insufficient resources, ask users to try again
|
|
return arm_fsm_rt_wait_for_res;
|
|
}
|
|
|
|
|
|
if (NULL == this.Target.ptRegion) {
|
|
//! use target region instead
|
|
this.Target.ptRegion = &(this.Target.ptTile->tRegion);
|
|
|
|
tTargetRegion.tSize = (*this.Target.ptRegion).tSize;
|
|
} else {
|
|
|
|
tTargetRegion = *this.Target.ptRegion;
|
|
}
|
|
|
|
//! handle the offset of the target tile
|
|
do {
|
|
//arm_2d_tile_t tValidTargetTile;
|
|
arm_2d_region_t tValidRegion;
|
|
arm_2d_location_t tOffset;
|
|
if (NULL == arm_2d_tile_get_root(this.Target.ptTile, &tValidRegion, &tOffset)) {
|
|
//! nothing to draw, actually
|
|
return (arm_fsm_rt_t)ARM_2D_ERR_OUT_OF_REGION;
|
|
}
|
|
|
|
//! calculate the valid region in the view of the target tile
|
|
tValidRegion.tLocation = tOffset;
|
|
|
|
//! [Modify][Target.ptTile]
|
|
//this.Target.ptTile = arm_2d_tile_generate_child( this.Target.ptTile,
|
|
//this.use_as__arm_2d_op_core_t.Runtime.ptTargetTile
|
|
|
|
ptTarget = arm_2d_tile_generate_child( this.Target.ptTile,
|
|
&tValidRegion,
|
|
&tTile,
|
|
true);
|
|
//! [Modify][Target.ptTile]
|
|
//assert(NULL != this.Target.ptTile);
|
|
//assert(NULL != this.use_as__arm_2d_op_core_t.Runtime.ptTargetTile);
|
|
assert(NULL != ptTarget);
|
|
tTargetRegion.tLocation.iX -= tOffset.iX;
|
|
tTargetRegion.tLocation.iY -= tOffset.iY;
|
|
|
|
} while(0);
|
|
|
|
//! [Modify][Target.ptTile]
|
|
//tDrawRegion.tSize = this.Target.ptTile->tRegion.tSize;
|
|
//tDrawRegion.tSize
|
|
// = this.use_as__arm_2d_op_core_t.Runtime.ptTargetTile->tRegion.tSize;
|
|
tDrawRegion.tSize = ptTarget->tRegion.tSize;
|
|
if (!arm_2d_region_intersect( &tDrawRegion,
|
|
&tTargetRegion,
|
|
&tDrawRegion)) {
|
|
return (arm_fsm_rt_t)ARM_2D_ERR_OUT_OF_REGION;
|
|
}
|
|
|
|
|
|
//! drawing
|
|
do {
|
|
arm_2d_tile_t tTempTile = {0};
|
|
|
|
//! [Modify][Target.ptTile]
|
|
//if (NULL == arm_2d_tile_generate_child( this.Target.ptTile,
|
|
if (NULL == arm_2d_tile_generate_child(
|
|
//this.use_as__arm_2d_op_core_t.Runtime.ptTargetTile,
|
|
ptTarget,
|
|
&tTargetRegion,
|
|
&tTempTile, true)) {
|
|
break;
|
|
}
|
|
#if 0
|
|
switch (OP_CORE.ptOp->Info.Colour.u3ColourSZ) {
|
|
case ARM_2D_COLOUR_SZ_8BIT:
|
|
case ARM_2D_COLOUR_SZ_16BIT:
|
|
case ARM_2D_COLOUR_SZ_32BIT:
|
|
tResult = __arm_2d_big_pixel_tile_pave(ptThis, ptSource, &tTile, wMode);
|
|
break;
|
|
default:
|
|
tResult = (arm_fsm_rt_t)ARM_2D_ERR_NOT_SUPPORT;
|
|
break;
|
|
}
|
|
#else
|
|
if (OP_CORE.ptOp->Info.Colour.u3ColourSZ >= ARM_2D_COLOUR_SZ_8BIT) {
|
|
tResult = __arm_2d_tile_process( ptThis,
|
|
&tTempTile);
|
|
} else {
|
|
tResult = (arm_fsm_rt_t)ARM_2D_ERR_NOT_SUPPORT;
|
|
}
|
|
#endif
|
|
} while(0);
|
|
|
|
return tResult;
|
|
}
|
|
|
|
static
|
|
arm_fsm_rt_t __arm_2d_op_frontend_control( arm_2d_op_core_t *ptOP)
|
|
{
|
|
/*TODO: add support for control operations*/
|
|
return (arm_fsm_rt_t)ARM_2D_ERR_NOT_SUPPORT;
|
|
}
|
|
|
|
static
|
|
arm_fsm_rt_t __arm_2d_op_frontend_region_process_with_src( arm_2d_op_core_t *ptOP)
|
|
{
|
|
ARM_2D_IMPL(arm_2d_op_src_t, ptOP)
|
|
|
|
arm_fsm_rt_t tResult;
|
|
arm_2d_tile_t tTile = {0};
|
|
arm_2d_region_t tDrawRegion = {0};
|
|
arm_2d_region_t tTargetRegion = {0};
|
|
const arm_2d_tile_t *ptTarget = NULL;
|
|
|
|
if (!__arm_2d_op_ensure_resource(ptOP, 4)) {
|
|
//! insufficient resources, ask users to try again
|
|
return arm_fsm_rt_wait_for_res;
|
|
}
|
|
|
|
|
|
if (NULL == this.Target.ptRegion) {
|
|
//! use target region instead
|
|
this.Target.ptRegion = &(this.Target.ptTile->tRegion);
|
|
|
|
tTargetRegion.tSize = (*this.Target.ptRegion).tSize;
|
|
} else {
|
|
|
|
tTargetRegion = *this.Target.ptRegion;
|
|
}
|
|
|
|
//! handle the offset of the target tile
|
|
do {
|
|
//arm_2d_tile_t tValidTargetTile;
|
|
|
|
arm_2d_region_t tValidRegion;
|
|
arm_2d_location_t tOffset;
|
|
if (NULL == arm_2d_tile_get_root(this.Target.ptTile, &tValidRegion, &tOffset)) {
|
|
//! nothing to draw, actually
|
|
return (arm_fsm_rt_t)ARM_2D_ERR_OUT_OF_REGION;
|
|
}
|
|
|
|
//! calculate the valid region in the view of the target tile
|
|
tValidRegion.tLocation = tOffset;
|
|
//if (tOffset.iX != 0 || tOffset.iY != 0) {
|
|
//!! [Modify][Target.ptTile]
|
|
//this.Target.ptTile = arm_2d_tile_generate_child( this.Target.ptTile,
|
|
//this.use_as__arm_2d_op_core_t.Runtime.ptTargetTile
|
|
ptTarget = arm_2d_tile_generate_child( this.Target.ptTile,
|
|
&tValidRegion,
|
|
&tTile,
|
|
true);
|
|
//!! [Modify][Target.ptTile]
|
|
//assert(NULL != this.Target.ptTile);
|
|
//assert(NULL != this.use_as__arm_2d_op_core_t.Runtime.ptTargetTile);
|
|
assert(NULL != ptTarget);
|
|
tTargetRegion.tLocation.iX -= tOffset.iX;
|
|
tTargetRegion.tLocation.iY -= tOffset.iY;
|
|
//}
|
|
|
|
} while(false);
|
|
|
|
|
|
|
|
if ( this.wMode & ARM_2D_CP_MODE_FILL) {
|
|
/* quickly ignore non visiable area, only for FILL mode */
|
|
if (tTargetRegion.tLocation.iX < 0) {
|
|
int_fast16_t iX = tTargetRegion.tLocation.iX;
|
|
|
|
tTargetRegion.tLocation.iX %= this.Source.ptTile->tRegion.tSize.iWidth;
|
|
|
|
//! calculate the delta
|
|
iX = tTargetRegion.tLocation.iX - iX;
|
|
|
|
//! update the width to make sure the range won't be expanded mistakenly
|
|
tTargetRegion.tSize.iWidth -= iX;
|
|
}
|
|
|
|
if (tTargetRegion.tLocation.iY < 0) {
|
|
int_fast16_t iY = tTargetRegion.tLocation.iY;
|
|
tTargetRegion.tLocation.iY %= this.Source.ptTile->tRegion.tSize.iHeight;
|
|
|
|
//! calculate the delta
|
|
iY = tTargetRegion.tLocation.iY - iY;
|
|
|
|
//! update the width to make sure the range won't be expanded mistakenly
|
|
tTargetRegion.tSize.iHeight -= iY;
|
|
}
|
|
}
|
|
|
|
//!! [Modify][Target.ptTile]
|
|
//tDrawRegion.tSize = this.Target.ptTile->tRegion.tSize;
|
|
//tDrawRegion.tSize = this.use_as__arm_2d_op_core_t.Runtime.ptTargetTile->tRegion.tSize;
|
|
tDrawRegion.tSize = ptTarget->tRegion.tSize;
|
|
if (!arm_2d_region_intersect( &tDrawRegion,
|
|
&tTargetRegion,
|
|
&tDrawRegion)) {
|
|
//! no overlapping
|
|
return (arm_fsm_rt_t)ARM_2D_ERR_OUT_OF_REGION;
|
|
}
|
|
|
|
if ( (tTargetRegion.tLocation.iX < 0)
|
|
|| (tTargetRegion.tLocation.iY < 0)) {
|
|
/*! draw the top left corner */
|
|
/*
|
|
HOW IT WORKS:
|
|
|
|
source tile (with negative relative location)
|
|
+------------------------------------+
|
|
| |
|
|
| +------------------------------+-- ... --+
|
|
| |//////////////////////////////| |
|
|
| |//ACTUAL DRAWING PART/////////| |
|
|
| |//////////////////////////////| |
|
|
+-----+------------------------------+-- ... --|
|
|
| | |
|
|
... ... ...
|
|
| | |
|
|
+------------------------------+-- ... --+
|
|
*/
|
|
arm_2d_region_t tClippdRegion;
|
|
tResult = __tile_clipped_pave( &this,
|
|
ptTarget,
|
|
&tTargetRegion,
|
|
&tClippdRegion,
|
|
this.wMode & ~ARM_2D_CP_MODE_FILL);
|
|
|
|
if (tResult < 0) {
|
|
return tResult;
|
|
}
|
|
|
|
if (this.wMode & ARM_2D_CP_MODE_FILL) { /*!< fill mode */
|
|
/*! draw the partial header */
|
|
/*
|
|
HOW IT WORKS:
|
|
|
|
source tile (with negative relative location)
|
|
+------------------+------------------------------------+-- ... --+
|
|
| | IGNORED HEADER PART | repeat |
|
|
| +---------------+------------------------------------+-- ... --+
|
|
| | |////////////////////////////////////|/////////|
|
|
| |Clipped Region |////ACTUAL DRAWING PART/////////////|/repeat//|
|
|
| | |////////////////////////////////////|/////////|
|
|
+--+---------------+------------------------------------+-- ... --+
|
|
| |
|
|
| |
|
|
+---------------------------------------------------------- ... --+
|
|
*/
|
|
|
|
if (tClippdRegion.tSize.iWidth < tDrawRegion.tSize.iWidth) {
|
|
//! something left to draw
|
|
|
|
arm_2d_region_t tHeaderRegion = tDrawRegion;
|
|
tHeaderRegion.tSize.iWidth = tDrawRegion.tSize.iWidth
|
|
- tClippdRegion.tSize.iWidth;
|
|
tHeaderRegion.tLocation.iX += tClippdRegion.tSize.iWidth;
|
|
tHeaderRegion.tSize.iHeight = tClippdRegion.tSize.iHeight
|
|
- tTargetRegion.tLocation.iY;
|
|
tHeaderRegion.tLocation.iY = tTargetRegion.tLocation.iY;
|
|
|
|
tResult = __tile_clipped_pave( &this,
|
|
ptTarget,
|
|
&tHeaderRegion,
|
|
NULL,
|
|
this.wMode);
|
|
|
|
//arm_2d_region_t tClippedRegion;
|
|
if (tResult < 0) {
|
|
return tResult;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*! draw the partial column */
|
|
/*
|
|
HOW IT WORKS:
|
|
|
|
source tile (with negative relative location)
|
|
+------------------------------------+
|
|
| |
|
|
| +------------------------------+-- ... --+
|
|
| | | |
|
|
| | | |
|
|
| | | |
|
|
+-----+------------------------------+ |
|
|
| |//////////////////////////////| |
|
|
| |//////////////////////////////| |
|
|
| |////ACTUAL DRAWING COLUMN/////| |
|
|
| |//////////////////////////////| |
|
|
| |//////////////////////////////| |
|
|
+-----+------------------------------+ |
|
|
| |//////////////////////////////| |
|
|
... ...///repeat////////////////////| |
|
|
| |//////////////////////////////| |
|
|
+-----+------------------------------+-- ... --+
|
|
*/
|
|
|
|
if (tClippdRegion.tSize.iHeight < tDrawRegion.tSize.iHeight) {
|
|
//! something left to draw
|
|
|
|
arm_2d_region_t tFirstColumnRegion = tDrawRegion;
|
|
tFirstColumnRegion.tSize.iHeight = tDrawRegion.tSize.iHeight - tClippdRegion.tSize.iHeight;
|
|
tFirstColumnRegion.tLocation.iY += tClippdRegion.tSize.iHeight;
|
|
tFirstColumnRegion.tSize.iWidth = tClippdRegion.tSize.iWidth
|
|
- tTargetRegion.tLocation.iX;
|
|
tFirstColumnRegion.tLocation.iX = tTargetRegion.tLocation.iX;
|
|
|
|
tResult = __tile_clipped_pave( &this,
|
|
ptTarget,
|
|
&tFirstColumnRegion,
|
|
NULL,
|
|
this.wMode);
|
|
|
|
if (tResult < 0) {
|
|
return tResult;
|
|
}
|
|
}
|
|
|
|
|
|
/*! draw the normal non-negitive part */
|
|
/*
|
|
HOW IT WORKS:
|
|
|
|
source tile (with negative relative location)
|
|
+------------------------------------+
|
|
| |
|
|
| +------------------------------+-- ... --+
|
|
| | | |
|
|
| | | |
|
|
| | | |
|
|
+-----+------------------------------+-- ... --|
|
|
| |/////////|
|
|
| |/////////|
|
|
... ...///////...
|
|
| |/////////|
|
|
| |/////////|
|
|
+------------------------------+-- ... --+
|
|
*/
|
|
|
|
if ( (tClippdRegion.tSize.iWidth < tDrawRegion.tSize.iWidth)
|
|
&& (tClippdRegion.tSize.iHeight < tDrawRegion.tSize.iHeight)) {
|
|
|
|
arm_2d_region_t tNonNegRegion = tDrawRegion;
|
|
tNonNegRegion.tSize.iWidth = tDrawRegion.tSize.iWidth - tClippdRegion.tSize.iWidth;
|
|
tNonNegRegion.tSize.iHeight = tDrawRegion.tSize.iHeight - tClippdRegion.tSize.iHeight;
|
|
tNonNegRegion.tLocation.iX += tClippdRegion.tSize.iWidth;
|
|
tNonNegRegion.tLocation.iY += tClippdRegion.tSize.iHeight;
|
|
|
|
tResult = __tile_non_negtive_location_pave( &this,
|
|
this.Source.ptTile,
|
|
|
|
//! [Modify][Target.ptTile]
|
|
//this.Target.ptTile,
|
|
//this.use_as__arm_2d_op_core_t.Runtime.ptTargetTile,
|
|
ptTarget,
|
|
&tNonNegRegion,
|
|
this.wMode);
|
|
if (tResult < 0) {
|
|
return tResult;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
tResult = __tile_non_negtive_location_pave( &this,
|
|
this.Source.ptTile,
|
|
|
|
//! [Modify][Target.ptTile]
|
|
//this.Target.ptTile,
|
|
//this.use_as__arm_2d_op_core_t.Runtime.ptTargetTile,
|
|
ptTarget,
|
|
&tTargetRegion,
|
|
this.wMode);
|
|
}
|
|
|
|
return tResult;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------*
|
|
* Frontend *
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
arm_fsm_rt_t __arm_2d_op_depose(arm_2d_op_core_t *ptThis,
|
|
arm_fsm_rt_t tResult)
|
|
{
|
|
//arm_irq_safe
|
|
{
|
|
this.tResult = tResult;
|
|
this.Status.tValue =
|
|
((tResult < 0) ? __ARM_2D_OP_STATUS_IO_ERROR_msk : 0) |
|
|
__ARM_2D_OP_STATUS_CPL_msk ;
|
|
}
|
|
return tResult;
|
|
}
|
|
|
|
__WEAK
|
|
arm_fsm_rt_t __arm_2d_op_frontend_on_leave( arm_2d_op_core_t *ptThis,
|
|
arm_fsm_rt_t tResult)
|
|
{
|
|
return __arm_2d_op_depose(ptThis, tResult);
|
|
}
|
|
|
|
static void __arm_2d_op_use_default_frame_buffer(arm_2d_op_core_t *ptOP)
|
|
{
|
|
ARM_2D_IMPL(arm_2d_op_t, ptOP);
|
|
|
|
if ((intptr_t)-1 == (intptr_t)this.Target.ptTile) {
|
|
this.Target.ptTile = ARM_2D_CTRL.ptDefaultFrameBuffer;
|
|
}
|
|
}
|
|
|
|
|
|
arm_fsm_rt_t __arm_2d_op_frontend_op_decoder(arm_2d_op_core_t *ptThis)
|
|
{
|
|
arm_fsm_rt_t tResult;
|
|
|
|
//! decode operation
|
|
switch (this.ptOp->Info.Param.chValue &
|
|
( ARM_2D_OP_INFO_PARAM_HAS_SOURCE
|
|
//| ARM_2D_OP_INFO_PARAM_HAS_ORIGIN
|
|
| ARM_2D_OP_INFO_PARAM_HAS_TARGET
|
|
//| ARM_2D_OP_INFO_PARAM_HAS_SOURCE_MASK
|
|
//| ARM_2D_OP_INFO_PARAM_HAS_TARGET_MASK
|
|
)) {
|
|
|
|
case ( ARM_2D_OP_INFO_PARAM_HAS_SOURCE
|
|
| ARM_2D_OP_INFO_PARAM_HAS_TARGET):
|
|
__arm_2d_op_use_default_frame_buffer(ptThis);
|
|
/* operaion process target tile based on source tile */
|
|
tResult = __arm_2d_op_frontend_region_process_with_src(ptThis);
|
|
break;
|
|
|
|
case ARM_2D_OP_INFO_PARAM_HAS_TARGET:
|
|
__arm_2d_op_use_default_frame_buffer(ptThis);
|
|
/* operation which only processes target tile */
|
|
tResult = __arm_2d_op_frontend_region_process(ptThis);
|
|
break;
|
|
|
|
default:
|
|
/* control operation */
|
|
tResult = __arm_2d_op_frontend_control(ptThis);
|
|
}
|
|
|
|
if (ARM_2D_ERR_OUT_OF_REGION == tResult) {
|
|
if (ARM_2D_RUNTIME_FEATURE.TREAT_OUT_OF_RANGE_AS_COMPLETE) {
|
|
//! nothing to draw
|
|
tResult = arm_fsm_rt_cpl;
|
|
}
|
|
}
|
|
|
|
return tResult;
|
|
}
|
|
|
|
|
|
__WEAK
|
|
/*! \brief sync up with operation
|
|
*! \retval true sync up with operation
|
|
*! \retval false operation is busy
|
|
*/
|
|
bool arm_2d_op_wait_async(arm_2d_op_core_t *ptOP)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
|
|
__WEAK
|
|
/*! \brief sync up with operation
|
|
*! \retval true operation is busy
|
|
*! \retval false operation isn't busy
|
|
*/
|
|
bool __arm_2d_op_acquire(arm_2d_op_core_t *ptOP)
|
|
{
|
|
ARM_2D_IMPL(arm_2d_op_core_t, ptOP)
|
|
bool bResult = !this.Status.bIsBusy;
|
|
|
|
arm_irq_safe {
|
|
if (bResult) {
|
|
//! initialize operation
|
|
do {
|
|
this.tResult = arm_fsm_rt_async;
|
|
this.Status.tValue = 0; //! reset status
|
|
this.Status.bIsBusy = true; //! set busy flag
|
|
} while(0);
|
|
}
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
__WEAK
|
|
arm_fsm_rt_t __arm_2d_op_frontend(arm_2d_op_core_t *ptThis)
|
|
{
|
|
arm_fsm_rt_t tResult;
|
|
|
|
tResult = __arm_2d_op_frontend_op_decoder(ptThis);
|
|
|
|
return __arm_2d_op_frontend_on_leave(ptThis, tResult);
|
|
}
|
|
|
|
arm_fsm_rt_t __arm_2d_op_invoke(arm_2d_op_core_t *ptOP)
|
|
{
|
|
ARM_2D_IMPL(arm_2d_op_core_t, ptOP)
|
|
|
|
#if 0
|
|
if (this.Status.bIsBusy) {
|
|
return arm_fsm_rt_on_going;
|
|
}
|
|
|
|
//! initialize operation
|
|
do {
|
|
this.tResult = arm_fsm_rt_async;
|
|
this.Status.tValue = 0; //! reset status
|
|
this.Status.bIsBusy = true; //! set busy flag
|
|
} while(0);
|
|
#endif
|
|
|
|
return __arm_2d_op_frontend(ptThis);
|
|
}
|
|
|
|
|
|
/*! \brief initialise the whole arm-2d service
|
|
*! \param none
|
|
*! \return none
|
|
*/
|
|
|
|
void __arm_2d_init(void)
|
|
{
|
|
/*! initialise arm-2d control block */
|
|
memset(&ARM_2D_CTRL, 0, sizeof(struct __arm_2d_op_control));
|
|
}
|
|
|
|
/*! \brief set the default frame buffer
|
|
*! \param ptFramebuffer the new frame buffer, if NULL is given, no default
|
|
*! frame buffer will be used
|
|
*! \return the address of the old frame buffer
|
|
*/
|
|
arm_2d_tile_t *arm_2d_set_default_frame_buffer(const arm_2d_tile_t *ptFrameBuffer)
|
|
{
|
|
arm_2d_tile_t *ptOldBuffer = NULL;
|
|
|
|
arm_irq_safe {
|
|
ptOldBuffer = ARM_2D_CTRL.ptDefaultFrameBuffer;
|
|
ARM_2D_CTRL.ptDefaultFrameBuffer = (arm_2d_tile_t *)ptFrameBuffer;
|
|
}
|
|
|
|
return ptOldBuffer;
|
|
}
|
|
|
|
/*! \brief get the default frame buffer
|
|
*! \return the address of the default frame buffer
|
|
*/
|
|
arm_2d_tile_t *arm_2d_get_default_frame_buffer(void)
|
|
{
|
|
return ARM_2D_CTRL.ptDefaultFrameBuffer;
|
|
}
|
|
|
|
/*! \brief attach a user param (which could be a pointer) to specified OP
|
|
*! \param ptOP the address of the target OP (NULL means using the default OP)
|
|
*! \param pUserParam a user param (it can be used as a pointer)
|
|
*/
|
|
void arm_2d_set_user_param(arm_2d_op_core_t *ptOP, uintptr_t pUserParam)
|
|
{
|
|
ARM_2D_IMPL(arm_2d_op_core_t, ptOP);
|
|
|
|
this.pUserParam = pUserParam;
|
|
}
|
|
|
|
/*! \brief get the status of a specified OP
|
|
*! \param ptOP the address of the target OP (NULL means using the default OP)
|
|
*! \return the status
|
|
*/
|
|
arm_2d_op_status_t arm_2d_get_op_status(arm_2d_op_core_t *ptOP)
|
|
{
|
|
ARM_2D_IMPL(arm_2d_op_core_t, ptOP)
|
|
|
|
volatile arm_2d_op_status_t *ptStatus
|
|
= (volatile arm_2d_op_status_t *)&(this.Status);
|
|
|
|
return *ptStatus;
|
|
}
|
|
|
|
|
|
__WEAK
|
|
/*! \brief arm-2d pixel pipeline task entery
|
|
*! \note This function is *TRHEAD-SAFE*
|
|
*! \param none
|
|
*! \retval arm_fsm_rt_cpl The sub-task FIFO is empty, the caller, i.e. the host
|
|
*! RTOS thread can block itself by waiting for a semaphore which is
|
|
*! set by arm_2d_notif_sub_task_fifo_task_arrive()
|
|
*! \retval arm_fsm_rt_on_going The arm_2d_task issued one sub-task without
|
|
*! problem and it yields.
|
|
*! \retval arm_fsm_rt_async You shouldn't see this value
|
|
*! \retval arm_fsm_rt_wait_for_obj some algorithm or hardware accelerator wants
|
|
*! to sync-up with applications.
|
|
*! \retval (<0) Serious error is detected.
|
|
*/
|
|
arm_fsm_rt_t arm_2d_task(arm_2d_task_t *ptTask)
|
|
{
|
|
ARM_2D_UNUSED(ptTask);
|
|
return arm_fsm_rt_cpl;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------*
|
|
* Low Level IO Interfaces *
|
|
*----------------------------------------------------------------------------*/
|
|
|
|
const __arm_2d_op_info_t ARM_2D_OP_BARRIER = {
|
|
.Info = {
|
|
//! control operation
|
|
.Param = {
|
|
.bHasSource = false,
|
|
.bHasTarget = false,
|
|
},
|
|
.chOpIndex = __ARM_2D_OP_IDX_BARRIER,
|
|
|
|
.LowLevelIO = {
|
|
.ptCopyLike = NULL,
|
|
.ptFillLike = 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
|
|
|
|
#endif
|