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 */