1 /**
2  * @file lv_draw_pxp_fill.c
3  *
4  */
5 
6 /**
7  * Copyright 2020-2024 NXP
8  *
9  * SPDX-License-Identifier: MIT
10  */
11 
12 /*********************
13  *      INCLUDES
14  *********************/
15 
16 #include "lv_draw_pxp.h"
17 
18 #if LV_USE_PXP
19 #if LV_USE_DRAW_PXP
20 #include "lv_pxp_cfg.h"
21 #include "lv_pxp_utils.h"
22 
23 /*********************
24  *      DEFINES
25  *********************/
26 
27 /**********************
28  *      TYPEDEFS
29  **********************/
30 
31 /**********************
32  *  STATIC PROTOTYPES
33  **********************/
34 
35 static void _pxp_fill(uint8_t * dest_buf, const lv_area_t * dest_area, int32_t dest_stride,
36                       lv_color_format_t dest_cf, const lv_draw_fill_dsc_t * dsc);
37 
38 /**********************
39  *  STATIC VARIABLES
40  **********************/
41 
42 /**********************
43  *      MACROS
44  **********************/
45 
46 /**********************
47  *   GLOBAL FUNCTIONS
48  **********************/
49 
lv_draw_pxp_fill(lv_draw_unit_t * draw_unit,const lv_draw_fill_dsc_t * dsc,const lv_area_t * coords)50 void lv_draw_pxp_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc,
51                       const lv_area_t * coords)
52 {
53     if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
54         return;
55 
56     lv_layer_t * layer = draw_unit->target_layer;
57     lv_draw_buf_t * draw_buf = layer->draw_buf;
58 
59     lv_area_t rel_coords;
60     lv_area_copy(&rel_coords, coords);
61     lv_area_move(&rel_coords, -layer->buf_area.x1, -layer->buf_area.y1);
62 
63     lv_area_t rel_clip_area;
64     lv_area_copy(&rel_clip_area, draw_unit->clip_area);
65     lv_area_move(&rel_clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
66 
67     lv_area_t blend_area;
68     if(!lv_area_intersect(&blend_area, &rel_coords, &rel_clip_area))
69         return; /*Fully clipped, nothing to do*/
70 
71     _pxp_fill(draw_buf->data, &blend_area, draw_buf->header.stride, draw_buf->header.cf, dsc);
72 }
73 
74 /**********************
75  *   STATIC FUNCTIONS
76  **********************/
77 
_pxp_fill(uint8_t * dest_buf,const lv_area_t * dest_area,int32_t dest_stride,lv_color_format_t dest_cf,const lv_draw_fill_dsc_t * dsc)78 static void _pxp_fill(uint8_t * dest_buf, const lv_area_t * dest_area, int32_t dest_stride,
79                       lv_color_format_t dest_cf, const lv_draw_fill_dsc_t * dsc)
80 {
81     int32_t dest_w = lv_area_get_width(dest_area);
82     int32_t dest_h = lv_area_get_height(dest_area);
83 
84     lv_pxp_reset();
85 
86     uint8_t px_size = lv_color_format_get_size(dest_cf);
87 
88     /*OUT buffer configure*/
89     pxp_output_buffer_config_t outputConfig = {
90         .pixelFormat = pxp_get_out_px_format(dest_cf),
91         .interlacedMode = kPXP_OutputProgressive,
92         .buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + px_size * dest_area->x1),
93         .buffer1Addr = (uint32_t)NULL,
94         .pitchBytes = dest_stride,
95         .width = dest_w,
96         .height = dest_h
97     };
98 
99     PXP_SetOutputBufferConfig(PXP_ID, &outputConfig);
100 
101     if(dsc->opa >= (lv_opa_t)LV_OPA_MAX) {
102         /*Simple color fill without opacity - AS disabled*/
103         PXP_SetAlphaSurfacePosition(PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
104 
105     }
106     else {
107         /*Fill with opacity - AS used as source (same as OUT)*/
108         pxp_as_buffer_config_t asBufferConfig = {
109             .pixelFormat = pxp_get_as_px_format(dest_cf),
110             .bufferAddr = outputConfig.buffer0Addr,
111             .pitchBytes = outputConfig.pitchBytes
112         };
113 
114         PXP_SetAlphaSurfaceBufferConfig(PXP_ID, &asBufferConfig);
115         PXP_SetAlphaSurfacePosition(PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
116     }
117 
118     /*Disable PS, use as color generator*/
119     PXP_SetProcessSurfacePosition(PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
120     PXP_SetProcessSurfaceBackGroundColor(PXP_ID, lv_color_to_u32(dsc->color));
121 
122     /**
123      * Configure Porter-Duff blending - src settings are unused for fill without opacity (opa = 0xff).
124      *
125      * Note: srcFactorMode and dstFactorMode are inverted in fsl_pxp.h:
126      * srcFactorMode is actually applied on PS alpha value
127      * dstFactorMode is actually applied on AS alpha value
128      */
129     pxp_porter_duff_config_t pdConfig = {
130         .enable = 1,
131         .dstColorMode = kPXP_PorterDuffColorNoAlpha,
132         .srcColorMode = kPXP_PorterDuffColorNoAlpha,
133         .dstGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha,
134         .srcGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha,
135         .dstFactorMode = kPXP_PorterDuffFactorStraight,
136         .srcFactorMode = (dsc->opa >= (lv_opa_t)LV_OPA_MAX) ? kPXP_PorterDuffFactorStraight : kPXP_PorterDuffFactorInversed,
137         .dstGlobalAlpha = dsc->opa,
138         .srcGlobalAlpha = dsc->opa,
139         .dstAlphaMode = kPXP_PorterDuffAlphaStraight, /*don't care*/
140         .srcAlphaMode = kPXP_PorterDuffAlphaStraight  /*don't care*/
141     };
142 
143     PXP_SetPorterDuffConfig(PXP_ID, &pdConfig);
144 
145     lv_pxp_run();
146 }
147 
148 #endif /*LV_USE_DRAW_PXP*/
149 #endif /*LV_USE_PXP*/
150