acid-drop

- Hacking the planet from a LilyGo T-Deck using custom firmware
git clone git://git.acid.vegas/acid-drop.git
Log | Files | Refs | Archive | README | LICENSE

lv_gpu_nxp_pxp.c (17617B)

      1 /**
      2  * @file lv_gpu_nxp_pxp.c
      3  *
      4  */
      5 
      6 /**
      7  * MIT License
      8  *
      9  * Copyright (c) 2020 NXP
     10  *
     11  * Permission is hereby granted, free of charge, to any person obtaining a copy
     12  * of this software and associated documentation files (the "Software"), to deal
     13  * in the Software without restriction, including without limitation the rights to
     14  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
     15  * the Software, and to permit persons to whom the Software is furnished to do so,
     16  * subject to the following conditions:
     17  *
     18  * The above copyright notice and this permission notice (including the next paragraph)
     19  * shall be included in all copies or substantial portions of the Software.
     20  *
     21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
     22  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
     23  * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
     24  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
     25  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
     26  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     27  *
     28  */
     29 
     30 /*********************
     31  *      INCLUDES
     32  *********************/
     33 
     34 #include "lv_gpu_nxp_pxp.h"
     35 
     36 #if LV_USE_GPU_NXP_PXP
     37 
     38 #include "../misc/lv_mem.h"
     39 #include "../misc/lv_log.h"
     40 
     41 #include "fsl_pxp.h"
     42 #include "fsl_cache.h"
     43 
     44 /*********************
     45  *      DEFINES
     46  *********************/
     47 
     48 #if LV_COLOR_16_SWAP
     49     #error Color swap not implemented. Disable LV_COLOR_16_SWAP feature.
     50 #endif
     51 
     52 #if LV_COLOR_DEPTH==16
     53     #define PXP_OUT_PIXEL_FORMAT kPXP_OutputPixelFormatRGB565
     54     #define PXP_AS_PIXEL_FORMAT kPXP_AsPixelFormatRGB565
     55     #define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatRGB565
     56 #else
     57     #error Only 16bit color depth is supported. Set LV_COLOR_DEPTH to 16.
     58 #endif
     59 
     60 /**********************
     61  *      TYPEDEFS
     62  **********************/
     63 
     64 /**********************
     65  *  STATIC PROTOTYPES
     66  **********************/
     67 
     68 static void lv_gpu_nxp_pxp_run(void);
     69 static void lv_gpu_nxp_pxp_blit_recolor(lv_color_t * dest, lv_coord_t dest_width, const lv_color_t * src,
     70                                         lv_coord_t src_width,
     71                                         lv_coord_t copy_width, lv_coord_t copy_height, lv_opa_t opa, lv_color_t recolor, lv_opa_t recolorOpa);
     72 
     73 /**********************
     74  *  STATIC VARIABLES
     75  **********************/
     76 
     77 static bool colorKeyEnabled = false;
     78 static uint32_t colorKey = 0x0;
     79 
     80 static bool recolorEnabled = false;
     81 static lv_color_t recolor = {.full = 0x0};
     82 static lv_opa_t recolorOpa = 0x0;
     83 
     84 static lv_nxp_pxp_cfg_t pxp_cfg;
     85 
     86 /**********************
     87  *      MACROS
     88  **********************/
     89 
     90 /**********************
     91  *   GLOBAL FUNCTIONS
     92  **********************/
     93 
     94 /**
     95  * Reset and initialize PXP device. This function should be called as a part
     96  * of display init sequence.
     97  *
     98  * @return LV_RES_OK: PXP init ok; LV_RES_INV: init error. See error log for more information.
     99  */
    100 lv_res_t lv_gpu_nxp_pxp_init(lv_nxp_pxp_cfg_t * cfg)
    101 {
    102     if(!cfg || !cfg->pxp_interrupt_deinit || !cfg->pxp_interrupt_init || !cfg->pxp_run) {
    103         LV_LOG_ERROR("PXP configuration error. Check callback pointers.");
    104         return LV_RES_INV;
    105     }
    106 
    107     PXP_Init(PXP);
    108     PXP_EnableCsc1(PXP, false); /*Disable CSC1, it is enabled by default.*/
    109     PXP_EnableInterrupts(PXP, kPXP_CompleteInterruptEnable);
    110 
    111     pxp_cfg = *cfg;
    112     if(pxp_cfg.pxp_interrupt_init() != LV_RES_OK) {
    113         PXP_Deinit(PXP);
    114         LV_LOG_ERROR("PXP interrupt init error. Check pxp_interrupt_init callback.");
    115         return LV_RES_INV;
    116     }
    117 
    118     colorKey = lv_color_to32(LV_COLOR_CHROMA_KEY);
    119 
    120     return LV_RES_OK;
    121 }
    122 
    123 /**
    124  * Disable PXP device. Should be called during display deinit sequence.
    125  */
    126 void lv_gpu_nxp_pxp_deinit(void)
    127 {
    128     pxp_cfg.pxp_interrupt_deinit();
    129     PXP_DisableInterrupts(PXP, kPXP_CompleteInterruptEnable);
    130     PXP_Deinit(LV_GPU_NXP_PXP_ID);
    131 }
    132 
    133 /**
    134  * Fill area, with optional opacity.
    135  *
    136  * @param[in/out] dest_buf destination buffer
    137  * @param[in] dest_width width (stride) of destination buffer in pixels
    138  * @param[in] fill_area area to fill
    139  * @param[in] color color
    140  * @param[in] opa transparency of the color
    141  */
    142 void lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, lv_coord_t dest_width, const lv_area_t * fill_area, lv_color_t color,
    143                          lv_opa_t opa)
    144 {
    145     PXP_Init(LV_GPU_NXP_PXP_ID);
    146     PXP_EnableCsc1(LV_GPU_NXP_PXP_ID, false);     /*Disable CSC1, it is enabled by default.*/
    147     PXP_SetProcessBlockSize(PXP, kPXP_BlockSize16); /*Block size 16x16 for higher performance*/
    148 
    149     /*OUT buffer configure*/
    150     pxp_output_buffer_config_t outputConfig = {
    151         .pixelFormat    = PXP_OUT_PIXEL_FORMAT,
    152         .interlacedMode = kPXP_OutputProgressive,
    153         .buffer0Addr    = (uint32_t)(dest_buf + dest_width * fill_area->y1 + fill_area->x1),
    154         .buffer1Addr    = (uint32_t)NULL,
    155         .pitchBytes     = dest_width * sizeof(lv_color_t),
    156         .width          = fill_area->x2 - fill_area->x1 + 1,
    157         .height         = fill_area->y2 - fill_area->y1 + 1,
    158     };
    159 
    160     PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputConfig);
    161 
    162     if(opa > LV_OPA_MAX) {
    163         /*Simple color fill without opacity - AS disabled, PS as color generator*/
    164         PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); /*Disable AS.*/
    165         PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U); /*Disable PS.*/
    166         PXP_SetProcessSurfaceBackGroundColor(LV_GPU_NXP_PXP_ID, lv_color_to32(color));
    167     }
    168     else {
    169         /*Fill with opacity - AS used as source (same as OUT), PS used as color generator, blended together*/
    170         pxp_as_buffer_config_t asBufferConfig;
    171         pxp_porter_duff_config_t pdConfig;
    172 
    173         /*Set AS to OUT*/
    174         asBufferConfig.pixelFormat = PXP_AS_PIXEL_FORMAT;
    175         asBufferConfig.bufferAddr  = (uint32_t)outputConfig.buffer0Addr;
    176         asBufferConfig.pitchBytes  = outputConfig.pitchBytes;
    177 
    178         PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
    179         PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, fill_area->x2 - fill_area->x1 + 1,
    180                                     fill_area->y2 - fill_area->y1 + 1);
    181 
    182         /*Disable PS, use as color generator*/
    183         PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
    184         PXP_SetProcessSurfaceBackGroundColor(LV_GPU_NXP_PXP_ID, lv_color_to32(color));
    185 
    186         /*Configure Porter-Duff blending - For RGB 565 only!*/
    187         pdConfig.enable = 1;
    188         pdConfig.dstColorMode = kPXP_PorterDuffColorStraight;
    189         pdConfig.srcColorMode = kPXP_PorterDuffColorStraight;
    190         pdConfig.dstGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha;
    191         pdConfig.srcGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha;
    192         pdConfig.srcFactorMode = kPXP_PorterDuffFactorStraight;
    193         pdConfig.dstFactorMode = kPXP_PorterDuffFactorStraight;
    194         pdConfig.srcGlobalAlpha = opa;
    195         pdConfig.dstGlobalAlpha = 255 - opa;
    196         pdConfig.srcAlphaMode = kPXP_PorterDuffAlphaStraight; /*don't care*/
    197         pdConfig.dstAlphaMode = kPXP_PorterDuffAlphaStraight; /*don't care*/
    198         PXP_SetPorterDuffConfig(LV_GPU_NXP_PXP_ID, &pdConfig);
    199     }
    200 
    201     lv_gpu_nxp_pxp_run(); /*Start PXP task*/
    202 }
    203 
    204 /**
    205  * @brief BLock Image Transfer - copy rectangular image from src buffer to dst buffer with effects.
    206  *
    207  * By default, image is copied directly, with optional opacity configured by \p opa.
    208  * Color keying can be enabled by calling lv_gpu_nxp_pxp_enable_color_key() before calling this function.
    209  * Recoloring can be enabled by calling  lv_gpu_nxp_pxp_enable_recolor() before calling this function.
    210  * Note that color keying and recoloring at the same time is not supported and black rectangle is rendered.
    211  *
    212  * @param[in/out] dest destination buffer
    213  * @param[in] dest_width width (stride) of destination buffer in pixels
    214  * @param[in] src source buffer
    215  * @param[in] src_with width (stride) of source buffer in pixels
    216  * @param[in] copy_w width of area to be copied from src to dest
    217  * @param[in] copy_h height of area to be copied from src to dest
    218  * @param[in] opa opacity of the result
    219  */
    220 void lv_gpu_nxp_pxp_blit(lv_color_t * dest, lv_coord_t dest_width, const lv_color_t * src, lv_coord_t src_width,
    221                          lv_coord_t copy_width, lv_coord_t copy_height, lv_opa_t opa)
    222 {
    223 
    224     if(recolorEnabled) {  /*switch to recolor version of blit*/
    225         lv_gpu_nxp_pxp_blit_recolor(dest,  dest_width, src, src_width, copy_width, copy_height, opa, recolor, recolorOpa);
    226         return;
    227     };
    228 
    229     PXP_Init(PXP);
    230     PXP_EnableCsc1(PXP, false);     /*Disable CSC1, it is enabled by default.*/
    231     PXP_SetProcessBlockSize(PXP, kPXP_BlockSize16); /*block size 16x16 for higher performance*/
    232 
    233     pxp_output_buffer_config_t outputBufferConfig;
    234     pxp_as_buffer_config_t asBufferConfig;
    235     pxp_as_blend_config_t asBlendConfig;
    236 
    237     asBlendConfig.alpha = opa;
    238     asBlendConfig.invertAlpha = false;
    239     asBlendConfig.alphaMode = kPXP_AlphaRop;
    240     asBlendConfig.ropMode = kPXP_RopMergeAs;
    241 
    242     if(opa >= LV_OPA_MAX && !colorKeyEnabled) {
    243         /*Simple blit, no effect - Disable PS buffer*/
    244         PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
    245     }
    246     else {
    247         /*Alpha blending or color keying enabled - PS must be enabled to fetch background pixels
    248           PS and OUT buffers are the same, blend will be done in-place*/
    249         pxp_ps_buffer_config_t psBufferConfig = {
    250             .pixelFormat = PXP_PS_PIXEL_FORMAT,
    251             .swapByte    = false,
    252             .bufferAddr  = (uint32_t)dest,
    253             .bufferAddrU = 0U,
    254             .bufferAddrV = 0U,
    255             .pitchBytes  = dest_width * sizeof(lv_color_t)
    256         };
    257         asBlendConfig.alphaMode = kPXP_AlphaOverride;
    258         PXP_SetProcessSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &psBufferConfig);
    259         PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, copy_width - 1, copy_height - 1);
    260     }
    261 
    262     /*AS buffer - source image*/
    263     asBufferConfig.pixelFormat = PXP_AS_PIXEL_FORMAT;
    264     asBufferConfig.bufferAddr  = (uint32_t)src;
    265     asBufferConfig.pitchBytes  = src_width * sizeof(lv_color_t);
    266     PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
    267     PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, copy_width - 1U, copy_height - 1U);
    268     PXP_SetAlphaSurfaceBlendConfig(LV_GPU_NXP_PXP_ID, &asBlendConfig);
    269 
    270     if(colorKeyEnabled) {
    271         PXP_SetAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, colorKey, colorKey);
    272     }
    273     PXP_EnableAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, colorKeyEnabled);
    274 
    275     /*Output buffer.*/
    276     outputBufferConfig.pixelFormat    = (pxp_output_pixel_format_t)PXP_OUT_PIXEL_FORMAT;
    277     outputBufferConfig.interlacedMode = kPXP_OutputProgressive;
    278     outputBufferConfig.buffer0Addr    = (uint32_t)dest;
    279     outputBufferConfig.buffer1Addr    = (uint32_t)0U;
    280     outputBufferConfig.pitchBytes     = dest_width * sizeof(lv_color_t);
    281     outputBufferConfig.width          = copy_width;
    282     outputBufferConfig.height         = copy_height;
    283     PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig);
    284 
    285     lv_gpu_nxp_pxp_run(); /* Start PXP task */
    286 }
    287 
    288 /**
    289  * @brief Enable color keying for subsequent calls to lv_gpu_nxp_pxp_blit()
    290  *
    291  * Color key is defined by  symbol in lv_conf.h
    292  */
    293 void lv_gpu_nxp_pxp_enable_color_key(void)
    294 {
    295     colorKeyEnabled = true;
    296 }
    297 
    298 /**
    299  * @brief Disable color keying for subsequent calls to lv_gpu_nxp_pxp_blit()
    300  *
    301  */
    302 void lv_gpu_nxp_pxp_disable_color_key(void)
    303 {
    304     colorKeyEnabled = false;
    305 }
    306 
    307 /**
    308  * @brief Enable recolor feature for subsequent calls to lv_gpu_nxp_pxp_blit()
    309  *
    310  * @param[in] color recolor value
    311  * @param[in] opa effect opacity
    312  */
    313 void lv_gpu_nxp_pxp_enable_recolor(lv_color_t color, lv_opa_t opa)
    314 {
    315     recolorEnabled = true;
    316     recolor = color;
    317     recolorOpa = opa;
    318 
    319 }
    320 
    321 /**
    322  * @brief Disable recolor feature for subsequent calls to lv_gpu_nxp_pxp_blit()
    323  */
    324 void lv_gpu_nxp_pxp_disable_recolor(void)
    325 {
    326     recolorEnabled = false;
    327 }
    328 
    329 /**********************
    330  *   STATIC FUNCTIONS
    331  **********************/
    332 
    333 /**
    334  * @brief Start PXP job and wait for results
    335  *
    336  * Function used internally to start PXP task according current device
    337  * configuration.
    338  */
    339 static void lv_gpu_nxp_pxp_run(void)
    340 {
    341     lv_disp_t * disp = _lv_refr_get_disp_refreshing();
    342 
    343     if(disp && disp->driver->clean_dcache_cb) {  /* Clean & invalidate cache */
    344         disp->driver->clean_dcache_cb(disp->driver);
    345     }
    346 
    347     pxp_cfg.pxp_run();
    348 }
    349 
    350 /**
    351  * @brief BLock Image Transfer - copy rectangular image from src buffer to dst buffer with recoloring.
    352  *
    353  * Note that color keying and recoloring at the same time is not supported and black rectangle is rendered.
    354  *
    355  * @param[in/out] dest destination buffer
    356  * @param[in] dest_width width (stride) of destination buffer in pixels
    357  * @param[in] src source buffer
    358  * @param[in] src_with width (stride) of source buffer in pixels
    359  * @param[in] copy_w width of area to be copied from src to dest
    360  * @param[in] copy_h height of area to be copied from src to dest
    361  * @param[in] opa opacity of the result
    362  * @param[in] recolor recolor value
    363  * @param[in] recolorOpa effect opacity
    364  */
    365 static void lv_gpu_nxp_pxp_blit_recolor(lv_color_t * dest, lv_coord_t dest_width, const lv_color_t * src,
    366                                         lv_coord_t src_width,
    367                                         lv_coord_t copy_width, lv_coord_t copy_height, lv_opa_t opa, lv_color_t recolor, lv_opa_t recolorOpa)
    368 {
    369     pxp_output_buffer_config_t outputBufferConfig;
    370     pxp_as_buffer_config_t asBufferConfig;
    371 
    372     if(colorKeyEnabled) {
    373         /*should never get here, recolor & color keying not supported. Draw black box instead.*/
    374         const lv_area_t fill_area = {.x1 = 0, .y1 = 0, .x2 = copy_width - 1, .y2 = copy_height - 1};
    375         lv_gpu_nxp_pxp_fill(dest, dest_width, &fill_area, lv_color_black(), LV_OPA_MAX);
    376         LV_LOG_WARN("Recoloring and color keying is not supported. Black rectangle rendered.");
    377         return ;
    378     }
    379     else {
    380         /*Recoloring without color keying*/
    381         if(opa > LV_OPA_MAX) {
    382             /*Recolor with full opacity - AS source image, PS color generator, OUT destination*/
    383             PXP_Init(PXP);
    384             PXP_EnableCsc1(PXP, false); /*Disable CSC1, it is enabled by default.*/
    385             PXP_SetProcessBlockSize(PXP, kPXP_BlockSize16); /*block size 16x16 for higher performance*/
    386 
    387             /*AS buffer - source image*/
    388             asBufferConfig.pixelFormat = PXP_AS_PIXEL_FORMAT;
    389             asBufferConfig.bufferAddr  = (uint32_t)src;
    390             asBufferConfig.pitchBytes  = src_width * sizeof(lv_color_t);
    391             PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
    392             PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, copy_width - 1U, copy_height - 1U);
    393 
    394             /*Disable PS buffer, use as color generator*/
    395             PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
    396             PXP_SetProcessSurfaceBackGroundColor(LV_GPU_NXP_PXP_ID, lv_color_to32(recolor));
    397 
    398             /*Output buffer*/
    399             outputBufferConfig.pixelFormat    = (pxp_output_pixel_format_t)PXP_OUT_PIXEL_FORMAT;
    400             outputBufferConfig.interlacedMode = kPXP_OutputProgressive;
    401             outputBufferConfig.buffer0Addr    = (uint32_t)dest;
    402             outputBufferConfig.buffer1Addr    = (uint32_t)0U;
    403             outputBufferConfig.pitchBytes     = dest_width * sizeof(lv_color_t);
    404             outputBufferConfig.width          = copy_width;
    405             outputBufferConfig.height         = copy_height;
    406             PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig);
    407 
    408             pxp_porter_duff_config_t pdConfig;
    409 
    410             /*Configure Porter-Duff blending - For RGB 565 only!*/
    411             pdConfig.enable = 1;
    412             pdConfig.dstColorMode = kPXP_PorterDuffColorStraight;
    413             pdConfig.srcColorMode = kPXP_PorterDuffColorStraight;
    414             pdConfig.dstGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha;
    415             pdConfig.srcGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha;
    416             pdConfig.srcFactorMode = kPXP_PorterDuffFactorStraight;
    417             pdConfig.dstFactorMode = kPXP_PorterDuffFactorStraight;
    418             pdConfig.srcGlobalAlpha = recolorOpa;
    419             pdConfig.dstGlobalAlpha = 255 - recolorOpa;
    420             pdConfig.srcAlphaMode = kPXP_PorterDuffAlphaStraight; /*don't care*/
    421             pdConfig.dstAlphaMode = kPXP_PorterDuffAlphaStraight; /*don't care*/
    422             PXP_SetPorterDuffConfig(LV_GPU_NXP_PXP_ID, &pdConfig);
    423 
    424             lv_gpu_nxp_pxp_run(); /*Start PXP task*/
    425 
    426         }
    427         else {
    428             /*Recolor with transparency*/
    429 
    430             /*Step 1: Recolor with full opacity to temporary buffer*/
    431             lv_color_t * tmpBuf  = (lv_color_t *)lv_mem_buf_get(copy_width * copy_height * sizeof(lv_color_t));
    432             lv_gpu_nxp_pxp_blit_recolor(tmpBuf, copy_width, src, src_width, copy_width, copy_height, LV_OPA_COVER, recolor,
    433                                         recolorOpa);
    434 
    435             /*Step 2: BLIT temporary results with required opacity to output*/
    436             lv_gpu_nxp_pxp_disable_recolor(); /*make sure to take BLIT path, not the recolor*/
    437             lv_gpu_nxp_pxp_blit(dest, dest_width, tmpBuf, copy_width, copy_width, copy_height, opa);
    438             lv_gpu_nxp_pxp_enable_recolor(recolor, recolorOpa); /*restore state*/
    439 
    440             /*Step 3: Clean-up memory*/
    441             lv_mem_buf_release(tmpBuf);
    442         }
    443     }
    444 }
    445 
    446 #endif /* LV_USE_GPU_NXP_PXP */