From c9d359500077b66a0df971580815b2c10b4f3627 Mon Sep 17 00:00:00 2001 From: Gabriel Wang Date: Sun, 28 Jan 2024 19:00:25 +0000 Subject: [PATCH] add initial implementation for screen rotation 90 degree. --- Helper/Include/arm_2d_helper_pfb.h | 117 +++++++++++++++++- Helper/Source/arm_2d_helper_pfb.c | 58 ++++++++- .../platform/Virtual_TFT_Port.h | 11 +- .../platform/arm_2d_disp_adapter_0.c | 38 +++++- .../platform/arm_2d_disp_adapter_0.h | 23 +++- 5 files changed, 233 insertions(+), 14 deletions(-) diff --git a/Helper/Include/arm_2d_helper_pfb.h b/Helper/Include/arm_2d_helper_pfb.h index 47dd86d70..806bd17a5 100644 --- a/Helper/Include/arm_2d_helper_pfb.h +++ b/Helper/Include/arm_2d_helper_pfb.h @@ -21,8 +21,8 @@ * Title: #include "arm_2d_helper_pfb.h" * Description: Public header file for the PFB helper service * - * $Date: 27. Dec 2023 - * $Revision: V.1.7.8 + * $Date: 28. Jan 2024 + * $Revision: V.1.8.0 * * Target Processor: Cortex-M cores * -------------------------------------------------------------------- */ @@ -992,6 +992,119 @@ ARM_NONNULL(1,2) bool __arm_2d_helper_3fb_draw_bitmap(arm_2d_helper_3fb_t *ptThis, const arm_2d_pfb_t *ptPFB); +/*! + * \brief rotate a given gray8 PFB for 90 degree + * \param[in] ptOrigin the original PFB + * \param[in] ptScratch A scratch PFB + * \param[in] ptScreenSize the screen size + * \return arm_2d_pfb_t * the output PFB + */ +extern +arm_2d_pfb_t * __arm_2d_helper_pfb_rotate90_gray8( + arm_2d_pfb_t *ptOrigin, + arm_2d_pfb_t *ptScratch, + const arm_2d_size_t *ptScreenSize); +/*! + * \brief rotate a given gray8 PFB for 180 degree + * \param[in] ptOrigin the original PFB + * \param[in] ptScratch A scratch PFB + * \param[in] ptScreenSize the screen size + * \return arm_2d_pfb_t * the output PFB + */ +extern +arm_2d_pfb_t * __arm_2d_helper_pfb_rotate180_gray8( + arm_2d_pfb_t *ptOrigin, + arm_2d_pfb_t *ptScratch, + const arm_2d_size_t *ptScreenSize); +/*! + * \brief rotate a given gray8 PFB for 270 degree + * \param[in] ptOrigin the original PFB + * \param[in] ptScratch A scratch PFB + * \param[in] ptScreenSize the screen size + * \return arm_2d_pfb_t * the output PFB + */ +extern +arm_2d_pfb_t * __arm_2d_helper_pfb_rotate270_gray8( + arm_2d_pfb_t *ptOrigin, + arm_2d_pfb_t *ptScratch, + const arm_2d_size_t *ptScreenSize); + +/*! + * \brief rotate a given rgb565 PFB for 90 degree + * \param[in] ptOrigin the original PFB + * \param[in] ptScratch A scratch PFB + * \param[in] ptScreenSize the screen size + * \return arm_2d_pfb_t * the output PFB + */ +extern +arm_2d_pfb_t * __arm_2d_helper_pfb_rotate90_rgb565( + arm_2d_pfb_t *ptOrigin, + arm_2d_pfb_t *ptScratch, + const arm_2d_size_t *ptScreenSize); + +/*! + * \brief rotate a given rgb565 PFB for 180 degree + * \param[in] ptOrigin the original PFB + * \param[in] ptScratch A scratch PFB + * \param[in] ptScreenSize the screen size + * \return arm_2d_pfb_t * the output PFB + */ +extern +arm_2d_pfb_t * __arm_2d_helper_pfb_rotate180_rgb565( + arm_2d_pfb_t *ptOrigin, + arm_2d_pfb_t *ptScratch, + const arm_2d_size_t *ptScreenSize); + +/*! + * \brief rotate a given rgb565 PFB for 270 degree + * \param[in] ptOrigin the original PFB + * \param[in] ptScratch A scratch PFB + * \param[in] ptScreenSize the screen size + * \return arm_2d_pfb_t * the output PFB + */ +extern +arm_2d_pfb_t * __arm_2d_helper_pfb_rotate270_rgb565( + arm_2d_pfb_t *ptOrigin, + arm_2d_pfb_t *ptScratch, + const arm_2d_size_t *ptScreenSize); + +/*! + * \brief rotate a given cccn888 PFB for 90 degree + * \param[in] ptOrigin the original PFB + * \param[in] ptScratch A scratch PFB + * \param[in] ptScreenSize the screen size + * \return arm_2d_pfb_t * the output PFB + */ +extern +arm_2d_pfb_t * __arm_2d_helper_pfb_rotate90_cccn888( + arm_2d_pfb_t *ptOrigin, + arm_2d_pfb_t *ptScratch, + const arm_2d_size_t *ptScreenSize); +/*! + * \brief rotate a given cccn888 PFB for 180 degree + * \param[in] ptOrigin the original PFB + * \param[in] ptScratch A scratch PFB + * \param[in] ptScreenSize the screen size + * \return arm_2d_pfb_t * the output PFB + */ +extern +arm_2d_pfb_t * __arm_2d_helper_pfb_rotate180_cccn888( + arm_2d_pfb_t *ptOrigin, + arm_2d_pfb_t *ptScratch, + const arm_2d_size_t *ptScreenSize); + +/*! + * \brief rotate a given cccn888 PFB for 270 degree + * \param[in] ptOrigin the original PFB + * \param[in] ptScratch A scratch PFB + * \param[in] ptScreenSize the screen size + * \return arm_2d_pfb_t * the output PFB + */ +extern +arm_2d_pfb_t * __arm_2d_helper_pfb_rotate270_cccn888( + arm_2d_pfb_t *ptOrigin, + arm_2d_pfb_t *ptScratch, + const arm_2d_size_t *ptScreenSize); /*! @} */ diff --git a/Helper/Source/arm_2d_helper_pfb.c b/Helper/Source/arm_2d_helper_pfb.c index 0cff61ebe..4d96070c9 100644 --- a/Helper/Source/arm_2d_helper_pfb.c +++ b/Helper/Source/arm_2d_helper_pfb.c @@ -21,8 +21,8 @@ * Title: #include "arm_2d_helper_pfb.c" * Description: the pfb helper service source code * - * $Date: 27. Dec 2023 - * $Revision: V.1.7.8 + * $Date: 28. Jan 2024 + * $Revision: V.1.8.0 * * Target Processor: Cortex-M cores * -------------------------------------------------------------------- */ @@ -3278,3 +3278,57 @@ void arm_2d_helper_transform_update_value( arm_2d_helper_transform_t *ptThis, } } +/*----------------------------------------------------------------------------* + * Rotate PFB Helper * + *----------------------------------------------------------------------------*/ + + +__WEAK +void __arm_2d_rotate_90_rgb565( uint16_t * __restrict phwOrigin, + uint16_t * __restrict phwOutput, + int16_t iOriginWidth, + int16_t iOriginHeight) +{ + int16_t iOutputWidth = iOriginHeight; + + for(int16_t iOriginX = 0; iOriginX < iOriginWidth; iOriginX++) { + int16_t iOriginColumn = iOriginX; + + uint16_t * __restrict phwOutputLine = &phwOutput[iOriginColumn * iOutputWidth]; + + for(int16_t iOriginY = iOriginHeight - 1; iOriginY >= 0; iOriginY--) { + *phwOutputLine++ = phwOrigin[iOriginY * iOriginWidth]; + } + phwOrigin++; + } +} + +arm_2d_pfb_t * __arm_2d_helper_pfb_rotate90_rgb565( arm_2d_pfb_t *ptOrigin, + arm_2d_pfb_t *ptScratch, + const arm_2d_size_t *ptScreenSize) +{ + assert(NULL != ptOrigin); + assert(NULL != ptScratch); + + uint16_t * __restrict phwOrigin = (uint16_t * __restrict)ptOrigin->tTile.phwBuffer; + uint16_t * __restrict phwOutput = (uint16_t * __restrict)ptScratch->tTile.phwBuffer; + + int16_t iWidth = ptOrigin->tTile.tRegion.tSize.iWidth; + int16_t iHeight = ptOrigin->tTile.tRegion.tSize.iHeight; + + __arm_2d_rotate_90_rgb565(phwOrigin, phwOutput, iWidth, iHeight); + + ptOrigin->tTile.tRegion.tSize.iWidth = iHeight; + ptOrigin->tTile.tRegion.tSize.iHeight = iWidth; + + arm_2d_location_t tNewLocation = { + ptScreenSize->iHeight - (ptOrigin->tTile.tRegion.tLocation.iY + iHeight - 1) - 1, + ptOrigin->tTile.tRegion.tLocation.iX, + }; + + ptOrigin->tTile.tRegion.tLocation = tNewLocation; + ptOrigin->tTile.phwBuffer = phwOutput; + ptScratch->tTile.phwBuffer = phwOrigin; + + return ptOrigin; +} diff --git a/examples/[template][pc][vscode]/platform/Virtual_TFT_Port.h b/examples/[template][pc][vscode]/platform/Virtual_TFT_Port.h index adcf09217..660bde6c7 100644 --- a/examples/[template][pc][vscode]/platform/Virtual_TFT_Port.h +++ b/examples/[template][pc][vscode]/platform/Virtual_TFT_Port.h @@ -13,8 +13,15 @@ extern "C" { // // 虚拟屏幕设定参数,即需要一个什么样的屏幕 // -#define VT_WIDTH __DISP0_CFG_SCEEN_WIDTH__ -#define VT_HEIGHT __DISP0_CFG_SCEEN_HEIGHT__ +#if __DISP0_CFG_ROTATE_SCREEN__ == __DISP0_SCREEN_ROTATE_90__\ + || __DISP0_CFG_ROTATE_SCREEN__ == __DISP0_SCREEN_ROTATE_270__ +# define VT_WIDTH __DISP0_CFG_SCEEN_HEIGHT__ +# define VT_HEIGHT __DISP0_CFG_SCEEN_WIDTH__ +#else +# define VT_WIDTH __DISP0_CFG_SCEEN_WIDTH__ +# define VT_HEIGHT __DISP0_CFG_SCEEN_HEIGHT__ +#endif + #define VT_COLOR_DEPTH __DISP0_CFG_COLOUR_DEPTH__ #define VT_VIRTUAL_MACHINE 0 /*Different rendering should be used if running in a Virtual machine*/ diff --git a/examples/[template][pc][vscode]/platform/arm_2d_disp_adapter_0.c b/examples/[template][pc][vscode]/platform/arm_2d_disp_adapter_0.c index b4419cfc0..2b47175c4 100644 --- a/examples/[template][pc][vscode]/platform/arm_2d_disp_adapter_0.c +++ b/examples/[template][pc][vscode]/platform/arm_2d_disp_adapter_0.c @@ -211,6 +211,26 @@ IMPL_PFB_ON_DRAW(__disp_adapter0_draw_navigation) } #endif +static arm_2d_pfb_t * __rotate_screen(arm_2d_pfb_t *ptOrigin) +{ + /* get a scratch PFB */ + arm_2d_pfb_t *ptScratchPFB + = __arm_2d_helper_pfb_new(&DISP0_ADAPTER.use_as__arm_2d_helper_pfb_t); + assert(NULL != ptScratchPFB); + + __arm_2d_helper_pfb_rotate90_rgb565( + ptOrigin, + ptScratchPFB, + (const arm_2d_size_t[]){__DISP0_CFG_SCEEN_WIDTH__, + __DISP0_CFG_SCEEN_HEIGHT__}); + + /* free scratch */ + __arm_2d_helper_pfb_free( &DISP0_ADAPTER.use_as__arm_2d_helper_pfb_t, + ptScratchPFB); + + return ptOrigin; +} + #if __DISP0_CFG_ENABLE_3FB_HELPER_SERVICE__ __WEAK IMPL_PFB_ON_LOW_LV_RENDERING(__disp_adapter0_pfb_render_handler) @@ -299,9 +319,15 @@ IMPL_PFB_ON_LOW_LV_RENDERING(__disp_adapter0_pfb_render_handler) * Meanwhile, in developing stage, this method can ensure a robust flushing. */ + + __WEAK IMPL_PFB_ON_LOW_LV_RENDERING(__disp_adapter0_pfb_render_handler) { +#if __DISP0_CFG_ROTATE_SCREEN__ != __DISP0_SCREEN_NO_ROTATION__ + ptPFB = __rotate_screen((arm_2d_pfb_t *)ptPFB); +#endif + const arm_2d_tile_t *ptTile = &(ptPFB->tTile); ARM_2D_UNUSED(pTarget); @@ -416,17 +442,20 @@ static void __user_scene_player_init(void) //! initialise FPB helper if (ARM_2D_HELPER_PFB_INIT( - &DISP0_ADAPTER.use_as__arm_2d_helper_pfb_t, //!< FPB Helper object + &DISP0_ADAPTER.use_as__arm_2d_helper_pfb_t, //!< FPB Helper object __DISP0_CFG_SCEEN_WIDTH__, //!< screen width __DISP0_CFG_SCEEN_HEIGHT__, //!< screen height - COLOUR_INT, //!< colour date type + COLOUR_INT, //!< colour date type __DISP0_CFG_PFB_BLOCK_WIDTH__, //!< PFB block width __DISP0_CFG_PFB_BLOCK_HEIGHT__, //!< PFB block height __DISP0_CFG_PFB_HEAP_SIZE__ //!< number of PFB in the PFB pool #if __DISP0_CFG_VIRTUAL_RESOURCE_HELPER__ \ && !__DISP0_CFG_USE_HEAP_FOR_VIRTUAL_RESOURCE_HELPER__ - + 3 + + 3 +#endif +#if __DISP0_CFG_ROTATE_SCREEN__ != __DISP0_SCREEN_NO_ROTATION__ + + (__DISP0_CFG_ROTATE_SCREEN__ > 0) #endif ,{ .evtOnLowLevelRendering = { @@ -447,7 +476,8 @@ static void __user_scene_player_init(void) .FrameBuffer.u3PixelHeightAlign = __DISP0_CFG_PFB_PIXEL_ALIGN_HEIGHT__, #if __DISP0_CFG_VIRTUAL_RESOURCE_HELPER__ \ && !__DISP0_CFG_USE_HEAP_FOR_VIRTUAL_RESOURCE_HELPER__ - .FrameBuffer.u4PoolReserve = 3, // reserve 3 PFB blocks for the virtual resource service + // reserve 3 PFB blocks for the virtual resource service + .FrameBuffer.u4PoolReserve = 3, #endif #if __DISP0_CFG_OPTIMIZE_DIRTY_REGIONS__ .DirtyRegion.ptRegions = s_tDirtyRegionList, diff --git a/examples/[template][pc][vscode]/platform/arm_2d_disp_adapter_0.h b/examples/[template][pc][vscode]/platform/arm_2d_disp_adapter_0.h index b85106a11..023ef4909 100644 --- a/examples/[template][pc][vscode]/platform/arm_2d_disp_adapter_0.h +++ b/examples/[template][pc][vscode]/platform/arm_2d_disp_adapter_0.h @@ -57,14 +57,14 @@ extern "C" { // The width of your screen // Default: 320 #ifndef __DISP0_CFG_SCEEN_WIDTH__ -# define __DISP0_CFG_SCEEN_WIDTH__ 800 +# define __DISP0_CFG_SCEEN_WIDTH__ 854 #endif // Height of the screen <8-32767> // The height of your screen // Default: 240 #ifndef __DISP0_CFG_SCEEN_HEIGHT__ -# define __DISP0_CFG_SCEEN_HEIGHT__ 600 +# define __DISP0_CFG_SCEEN_HEIGHT__ 480 #endif // Width of the PFB block @@ -76,7 +76,7 @@ extern "C" { // Height of the PFB block // The height of your PFB block size used in disp0 #ifndef __DISP0_CFG_PFB_BLOCK_HEIGHT__ -# define __DISP0_CFG_PFB_BLOCK_HEIGHT__ (__DISP0_CFG_SCEEN_HEIGHT__ / 10) +# define __DISP0_CFG_PFB_BLOCK_HEIGHT__ (__DISP0_CFG_SCEEN_HEIGHT__) #endif // Width Alignment of generated PFBs @@ -104,7 +104,7 @@ extern "C" { // <7=> 128 pixel // Make sure the y and height of the PFB is always aligned to 2^n pixels #ifndef __DISP0_CFG_PFB_PIXEL_ALIGN_HEIGHT__ -# define __DISP0_CFG_PFB_PIXEL_ALIGN_HEIGHT__ 0 +# define __DISP0_CFG_PFB_PIXEL_ALIGN_HEIGHT__ 2 #endif // PFB Block Count <1-65535> @@ -151,6 +151,21 @@ extern "C" { # define __DISP0_CFG_SWAP_RGB16_HIGH_AND_LOW_BYTES__ 0 #endif +#define __DISP0_SCREEN_NO_ROTATION__ 0 +#define __DISP0_SCREEN_ROTATE_90__ 1 +#define __DISP0_SCREEN_ROTATE_180__ 2 +#define __DISP0_SCREEN_ROTATE_270__ 3 + +// Rotate the Screen +// <__DISP0_SCREEN_NO_ROTATION__=> NO Rotate +// <__DISP0_SCREEN_ROTATE_90__=> 90 Degree +// <__DISP0_SCREEN_ROTATE_180__=> 180 Degree +// <__DISP0_SCREEN_ROTATE_270__=> 270 Degree +// Rotate the Screen for specified degrees. +#ifndef __DISP0_CFG_ROTATE_SCREEN__ +# define __DISP0_CFG_ROTATE_SCREEN__ __DISP0_SCREEN_ROTATE_90__ +#endif + // Enable the helper service for Asynchronous Flushing // Please select this option when using asynchronous flushing, e.g. DMA + ISR #ifndef __DISP0_CFG_ENABLE_ASYNC_FLUSHING__