Arm-2D  
2D Image Processing Library for Cortex-M Processors
arm_2d_helper_pfb.h
1/*
2 * Copyright (C) 2022 Arm Limited or its affiliates. All rights reserved.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the License); you may
7 * not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19/* ----------------------------------------------------------------------
20 * Project: Arm-2D Library
21 * Title: #include "arm_2d_helper_pfb.h"
22 * Description: Public header file for the PFB helper service
23 *
24 * $Date: 29. Nov 2023
25 * $Revision: V.1.7.6
26 *
27 * Target Processor: Cortex-M cores
28 * -------------------------------------------------------------------- */
29
30#ifndef __ARM_2D_HELPER_PFB_H__
31#define __ARM_2D_HELPER_PFB_H__
32
33/*============================ INCLUDES ======================================*/
34#include "arm_2d.h"
35
36#include "./__arm_2d_helper_common.h"
37
38#ifdef __cplusplus
39extern "C" {
40#endif
41
42
43#if defined(__clang__)
44# pragma clang diagnostic push
45# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
46# pragma clang diagnostic ignored "-Wpadded"
47#endif
48
49/*!
50 * \addtogroup gHelper 7 Helper Services
51 * @{
52 */
53
54/*============================ MACROS ========================================*/
55
56#define ARM_2D_FPS_MODE_RENDER_ONLY 0
57#define ARM_2D_FPS_MODE_REAL 1
58
59/*============================ MACROFIED FUNCTIONS ===========================*/
60
61/*!
62 * \brief a macro wrapper in uppercase to help initialising PFB service
63 * \param[in] __CB_ADDR the address of the arm_2d_helper_pfb_t object
64 * \param[in] __SCREEN_WIDTH the width of the screen
65 * \param[in] __SCREEN_HEIGHT the hight of the screen
66 * \param[in] __PIXEL_TYPE the integer type of the pixel, i.e. uint8_t, uint16_t,
67 * uint32_t
68 * \param[in] __WIDTH the width of the PFB block
69 * \param[in] __HEIGHT the height of the PFB block
70 * \note For the same number of pixels in a PFB block, please priority the width
71 * over height, for example, 240 * 1 is better than 30 * 8
72 * \param[in] __PFB_NUM the number of PFB blocks in the built-in PFB pool.
73 * \param[in] ... a code block to add additional initializer, see example below:
74 * \return arm_2d_err_t the result of the initialisation process
75 *
76 * \code {.c}
77
78 static ARM_NOINIT arm_2d_helper_pfb_t s_tExamplePFB;
79 ...
80 // initialise FPB helper
81 if (ARM_2D_HELPER_PFB_INIT(
82 &s_tExamplePFB, // FPB Helper object
83 __GLCD_CFG_SCEEN_WIDTH__, // screen width
84 __GLCD_CFG_SCEEN_HEIGHT__, // screen height
85 uint16_t, // colour date type
86 240, // PFB block width
87 1, // PFB block height
88 1, // number of PFB in the PFB pool
89 {
90 .evtOnLowLevelRendering = {
91 // callback for low level rendering
92 .fnHandler = &__pfb_render_handler,
93 },
94 .evtOnDrawing = {
95 // callback for drawing GUI
96 .fnHandler = &__pfb_draw_background_handler,
97 },
98 },
99 //.FrameBuffer.bSwapRGB16 = true,
100 ) < 0) {
101 //! error detected
102 assert(false);
103 }
104 * \endcode
105 *
106 */
107#define ARM_2D_HELPER_PFB_INIT( __CB_ADDR, /* PFB Helper object address */ \
108 __SCREEN_WIDTH, /* Screen width */ \
109 __SCREEN_HEIGHT,/* Screen height */ \
110 __PIXEL_TYPE, /* The type of the pixels */ \
111 __PFB_WIDTH, /* The width of the PFB block */\
112 __PFB_HEIGHT, /* The height of the PFB block*/\
113 __PFB_NUM, /* Block count in the PFB pool*/\
114 ... /* Event Handler */ \
115 ) \
116 ({ \
117 ARM_SECTION(".bss.noinit.arm_2d_pfb_pool") \
118 static struct { \
119 arm_2d_pfb_t tFPB; \
120 __ALIGNED(4) \
121 __PIXEL_TYPE tBuffer[(__PFB_WIDTH) * (__PFB_HEIGHT)]; \
122 } s_tPFBs[__PFB_NUM]; \
123 \
124 arm_2d_helper_pfb_cfg_t tCFG = { \
125 .tDisplayArea.tSize = { \
126 .iWidth = (__SCREEN_WIDTH), \
127 .iHeight = (__SCREEN_HEIGHT), \
128 }, \
129 \
130 .FrameBuffer.ptPFBs = (arm_2d_pfb_t *)s_tPFBs, \
131 .FrameBuffer.tFrameSize = { \
132 .iWidth = (__PFB_WIDTH), \
133 .iHeight = (__PFB_HEIGHT), \
134 }, \
135 .FrameBuffer.wBufferSize = sizeof(s_tPFBs[0].tBuffer), \
136 .FrameBuffer.hwPFBNum = dimof(s_tPFBs), \
137 .Dependency = \
138 __VA_ARGS__ \
139 }; \
140 \
141 arm_2d_helper_pfb_init((__CB_ADDR), &tCFG); \
142 })
143
144/*!
145 * \brief a macro wrapper to update the evtOnDrawring event handler
146 * \param[in] __CB_ADDR the address of the arm_2d_helper_pfb_t object
147 * \param[in] __HANDLER the new handler
148 * \param[in] ... [Optional] an address (of user defined structure) passed to the
149 * event handler.
150 * \return arm_2d_err_t the process result
151 */
152#define ARM_2D_HELPER_PFB_UPDATE_ON_DRAW_HANDLER( \
153 __CB_ADDR, /* PFB Helper object address */ \
154 __HANDLER, /* new on-draw-handler function*/\
155 ...) /* An optional target address */ \
156 arm_2d_helper_pfb_update_dependency((__CB_ADDR), \
157 ARM_2D_PFB_DEPEND_ON_DRAWING, \
158 (arm_2d_helper_pfb_dependency_t []) {{ \
159 .evtOnDrawing = { \
160 .fnHandler = (__HANDLER), \
161 .pTarget = (NULL,##__VA_ARGS__),\
162 }, \
163 }})
164
165
166#define __IMPL_ARM_2D_REGION_LIST(__NAME, ...) \
167 enum { \
168 __NAME##_offset = __COUNTER__, \
169 }; \
170 __VA_ARGS__ \
171 arm_2d_region_list_item_t __NAME[] = {
172
173
174#define IMPL_ARM_2D_REGION_LIST(__NAME, ...) \
175 __IMPL_ARM_2D_REGION_LIST(__NAME,##__VA_ARGS__)
176
177
178#define END_IMPL_ARM_2D_REGION_LIST(...) \
179 };
180
181#define __ADD_REGION_TO_LIST(__NAME, ...) \
182 { \
183 .ptNext = (arm_2d_region_list_item_t *) \
184 &(__NAME[__COUNTER__ - __NAME##_offset]), \
185 .tRegion = { \
186 __VA_ARGS__ \
187 }, \
188 }
189
190#define ADD_REGION_TO_LIST(__NAME, ...) \
191 __ADD_REGION_TO_LIST(__NAME, ##__VA_ARGS__)
192
193
194#define __ADD_LAST_REGION_TO_LIST(__NAME, ...) \
195 { \
196 .ptNext = NULL, \
197 .tRegion = { \
198 __VA_ARGS__ \
199 }, \
200 }
201
202#define ADD_LAST_REGION_TO_LIST(__NAME, ...) \
203 __ADD_LAST_REGION_TO_LIST(__NAME, ##__VA_ARGS__)
204
205
206#define IMPL_PFB_ON_DRAW(__NAME) IMPL_ON_DRAW_EVT(__NAME)
207
208
209#define IMPL_PFB_ON_LOW_LV_RENDERING(__NAME) \
210 void __NAME(void *pTarget, \
211 const arm_2d_pfb_t *ptPFB, \
212 bool bIsNewFrame)
213
214
215#define IMPL_PFB_ON_FRAME_SYNC_UP(__NAME) \
216 bool __NAME(void *pTarget)
217
218
219/*!
220 * \brief a macro wrapper in lowercase to help initialising PFB service
221 * \param[in] __CB_ADDR the address of the arm_2d_helper_pfb_t object
222 * \param[in] __SCREEN_WIDTH the width of the screen
223 * \param[in] __SCREEN_HEIGHT the hight of the screen
224 * \param[in] __PIXEL_TYPE the integer type of the pixel, i.e. uint8_t, uint16_t,
225 * uint32_t
226 * \param[in] __WIDTH the width of the PFB block
227 * \param[in] __HEIGHT the height of the PFB block
228 * \note For the same number of pixels in a PFB block, please priority the width
229 * over height, for example, 240 * 1 is better than 30 * 8
230 * \param[in] __PFB_NUM the number of PFB blocks in the built-in PFB pool.
231 * \param[in] ... a code block to add additional initializer, see example below:
232 * \return arm_2d_err_t the result of the initialisation process
233 *
234 * \code {.c}
235
236 static ARM_NOINIT arm_2d_helper_pfb_t s_tExamplePFB;
237 ...
238 // initialise FPB helper
239 if (init_arm_2d_helper_pfb(
240 &s_tExamplePFB, // FPB Helper object
241 __GLCD_CFG_SCEEN_WIDTH__, // screen width
242 __GLCD_CFG_SCEEN_HEIGHT__, // screen height
243 uint16_t, // colour date type
244 240, // PFB block width
245 1, // PFB block height
246 1, // number of PFB in the PFB pool
247 {
248 .evtOnLowLevelRendering = {
249 // callback for low level rendering
250 .fnHandler = &__pfb_render_handler,
251 },
252 .evtOnDrawing = {
253 // callback for drawing GUI
254 .fnHandler = &__pfb_draw_background_handler,
255 },
256 },
257 //.FrameBuffer.bSwapRGB16 = true,
258 ) < 0) {
259 //! error detected
260 assert(false);
261 }
262 * \endcode
263 *
264 */
265#define init_arm_2d_helper_pfb( __CB_ADDR, \
266 __SCREEN_WIDTH, \
267 __SCREEN_HEIGHT, \
268 __PIXEL_TYPE, \
269 __WIDTH, \
270 __HEIGHT, \
271 __PFB_NUM, \
272 ... \
273 ) \
274 ARM_2D_HELPER_PFB_INIT( \
275 __CB_ADDR, \
276 __SCREEN_WIDTH, \
277 __SCREEN_HEIGHT, \
278 __PIXEL_TYPE, \
279 __WIDTH, \
280 __HEIGHT, \
281 __PFB_NUM, \
282 ##__VA_ARGS__ \
283 )
284
285/*!
286 * \brief a macro wrapper to update the evtOnDrawring event handler
287 * \param[in] __CB_ADDR the address of the arm_2d_helper_pfb_t object
288 * \param[in] __HANDLER the new handler
289 * \param[in] ... [Optional] an address (of user defined structure) passed to the
290 * event handler.
291 * \return arm_2d_err_t the process result
292 */
293#define update_arm_2d_helper_pfb_on_draw_handler( \
294 __CB_ADDR, /* PFB Helper object address */ \
295 __HANDLER, /* new on-draw-handler function*/\
296 ...) /* An optional target address */ \
297 ARM_2D_HELPER_PFB_UPDATE_ON_DRAW_HANDLER( \
298 (__CB_ADDR), \
299 (__HANDLER),##__VA_ARGRS__)
300
301/*!
302 * \brief tell PFB helper that a low level LCD flushing work is complete
303 * \note This function is THREAD-SAFE, You can call this function asynchronously,
304 * e.g.
305 * - A ISR to indicate DMA-transfer complete event or
306 * - A different Thread
307 * \param[in] ptThis the PFB helper control block
308 * \param[in] ... the used PFB block.
309 * \note please do not use this parameter, it is only kept for backward
310 * compatability.
311 */
312#define arm_2d_helper_pfb_report_rendering_complete(__PFB_HELPER_PTR,...) \
313 __arm_2d_helper_pfb_report_rendering_complete((__PFB_HELPER_PTR), \
314 (NULL,##__VA_ARGS__))
315
316
317#define impl_arm_2d_region_list(__NAME, ...) \
318 IMPL_ARM_2D_REGION_LIST(__NAME,##__VA_ARGS__)
319#define add_region_to_list(__NAME, ...) \
320 ADD_REGION_TO_LIST(__NAME, ##__VA_ARGS__)
321#define add_last_region_to_list(__NAME, ...) \
322 ADD_LAST_REGION_TO_LIST(__NAME, ##__VA_ARGS__)
323#define end_impl_arm_2d_region_list(...) \
324 END_IMPL_ARM_2D_REGION_LIST(__VA_ARGS__)
325
326#define impl_pfb_on_draw(__NAME) IMPL_PFB_ON_DRAW(__NAME)
327#define impl_pfb_on_low_lv_rendering(__NAME) \
328 IMPL_PFB_ON_LOW_LV_RENDERING(__NAME)
329
330/*============================ TYPES =========================================*/
331
332/*!
333 * \brief direct mode helper service frame-buffer control block states
334 *
335 * \note state transition diagram
336 * <<< service initialization >>>
337 * |
338 * ARM_3FB_STATE_READY_FOR_FLUSH <------+
339 * | |
340 * ARM_3FB_STATE_FLUSHING |
341 * | |
342 * ARM_3FB_STATUS_UNUSED ---> ARM_3FB_STATE_READY_TO_DRAW |
343 * | |
344 * ARM_3FB_STATE_COPYING_AS_TARGET |
345 * |
346 * ARM_3FB_STATE_DRAWING |
347 * | |
348 * ARM_3FB_STATE_COPYING_AS_SOURCE -----+
349 *
350 */
351enum {
352 ARM_3FB_STATE_UNUSED = 0, //!< the FB hasn't been used
353 ARM_3FB_STATE_COPYING_AS_TARGET, //!< the FB is used as the target of frame copy, the previous state is ARM_3FB_STATE_FLUSHING (or ARM_3FB_STATE_UNUSED)
354 ARM_3FB_STATE_READY_TO_DRAW, //!< the FB is ready to draw, the previous state is ARM_3FB_STATE_COPYING_AS_TARGET
355 ARM_3FB_STATE_DRAWING, //!< the FB is used for drawing, the previous state is ARM_3FB_STATE_READY_TO_DRAW
356 ARM_3FB_STATE_COPYING_AS_SOURCE, //!< the FB is used as the source of frame copy, the previous state is ARM_3FB_STATE_READY_FOR_FLUSH
357 ARM_3FB_STATE_READY_TO_FLUSH, //!< the FB is ready for flushing and waiting for a v-sync event, the previous state is ARM_3FB_STATE_COPYING_AS_SOURCE
358 ARM_3FB_STATE_FLUSHING, //!< the FB is used for flushing, the previous state is ARM_3FB_STATE_READY_FOR_FLUSH
359};
360
362
363/*!
364 * \brief An interface for 2D-Copy.
365 * \param[in] pnSource the source image address
366 * \param[in] wSourceStride the stride of the source image
367 * \param[in] pnTarget the address in the target framebuffer
368 * \param[in] wTargetStride the stride of the target framebuffer
369 * \param[in] iWidth the safe width of the source image
370 * \param[in] iHeight the safe height of the source image
371 * \retval true the 2D copy is complete when leaving this function
372 * \retval false An async 2D copy request is sent to the DMA
373 */
374typedef
376 void *pObj,
377 uintptr_t pnSource,
378 uint32_t wSourceStride,
379 uintptr_t pnTarget,
380 uint32_t wTargetStride,
381 int16_t iWidth,
382 int16_t iHeight,
383 uint_fast8_t chBytePerPixel );
384
387 void *pObj;
389
390/*!
391 * \brief An interface for DMA memory-to-memory copy.
392 * If you have a DMA, you can implement this function by using
393 * __OVERRIDE_WEAK.
394 * You should implement an ISR for copy-complete event and call
395 * arm_2d_helper_3fb_report_dma_copy_complete() to notify the
396 * 3FB (direct mode) helper service.
397 *
398 * \param[in] ptThis the helper service control block
399 * \param[in] pObj the address of the user object
400 * \param[in] pnSource the source address of the memory block
401 * \param[in] pnTarget the target address
402 * \param[in] nDataItemCount the number of date items
403 * \param[in] chDataItemSize the size of each data item
404 */
405typedef
407 void *pObj,
408 uintptr_t pnSource,
409 uintptr_t pnTarget,
410 uint32_t nDataItemCount,
411 uint_fast8_t chDataItemSize);
412
415 void *pObj;
417
418/*!
419 * \brief configuration structure for the 3fb (direct mode) helper service
420 */
422 arm_2d_size_t tScreenSize; //!< the screen size
423 uint8_t chPixelBits; //!< the number of bits in one pixel
424 uintptr_t pnAddress[3]; //!< addresses of the 3 full-frame-buffer
425
426 arm_2d_helper_2d_copy_evt_t evtOn2DCopy;
427 arm_2d_helper_dma_copy_evt_t evtOnDMACopy;
429
430#define ARM_2D_3FB_INVALID_IDX 3
431
432/*!
433 * \brief the control block of the 3FB (direct mode) service
434 */
435typedef struct arm_2d_helper_3fb_t {
436ARM_PRIVATE(
438
439 struct {
440 uint8_t u2Drawing : 2; //!< FB pointer for drawing
441 uint8_t u2Flushing : 2; //!< FB pointer for flushing
442 uint8_t u2ReadyToFlush : 2; //!< FB pointer of ready to flush
443 uint8_t u2ReadyToDraw : 2; //!< FB pointer of ready to draw
444 uint8_t tState[3];
445 uintptr_t tSemaphore; //!< semaphore for async access
446 bool bFBCopyComplete; //!< a flag to indicate the completion of a DMA copy
447 } Runtime;
450
452
453/*!
454 * \brief the header of a PFB block
455 */
456typedef struct arm_2d_pfb_t {
457 struct arm_2d_pfb_t *ptNext; //!< next pfb block
458 arm_2d_helper_pfb_t *ptPFBHelper; //!< the pfb helper service current PFB block comes from
459 arm_2d_tile_t tTile; //!< descriptor
460 uint32_t u24Size : 24;
461 uint32_t : 7;
462 uint32_t bIsNewFrame : 1; //!< a flag to indicate the starting of a frame
464
465/*!
466 * \brief the node of a region list
467 *
468 */
470 struct arm_2d_region_list_item_t *ptNext; //!< the next node
471 arm_2d_region_t tRegion; //!< the region
472 uint8_t bIgnore : 1; //!< ignore this region
473 uint8_t bUpdated : 1; //!< this region item has been updated, PFB helper should refresh it again.
474 uint8_t : 6;
475
476ARM_PRIVATE(
477 struct arm_2d_region_list_item_t *ptInternalNext; //!< the next node in the internal list
478 uint8_t bFromInternalPool : 1; //!< a flag indicating whether this list item coming from the internal pool
479 uint8_t bFromHeap : 1; //!< whether this item comes from the HEAP
480 uint8_t : 6;
483
484/*!
485 * \brief the On Low Level Rendering event handler for the low level (LCD Driver)
486 *
487 * \param[in] pTarget a user attached target address
488 * \param[in] ptPFB the PFB block
489 * \param[in] bIsNewFrame a flag indicate the starting of a new frame
490 */
492 void *pTarget,
493 const arm_2d_pfb_t *ptPFB,
494 bool bIsNewFrame);
495
496/*!
497 * \brief on low level render event
498 */
500 arm_2d_helper_render_handler_t *fnHandler; //!< event handler function
501 void *pTarget; //!< user attached target
503
504
505
506/*!
507 * \brief the enumeration for events
508 *
509 */
510enum {
511 ARM_2D_PFB_DEPEND_ON_LOW_LEVEL_RENDERING = _BV(0), //!< On Low Level Rendering Event
512 ARM_2D_PFB_DEPEND_ON_DRAWING = _BV(1), //!< On Drawing Event
513 ARM_2D_PFB_DEPEND_ON_LOW_LEVEL_SYNC_UP = _BV(2), //!< On Low Level Sync-up Event
514 ARM_2D_PFB_DEPEND_ON_FRAME_SYNC_UP = _BV(3), //!< On Frame Sync-up Event
515 ARM_2D_PFB_DEPEND_ON_EACH_FRAME_CPL = _BV(4), //!< On Each Frame Complete Event
516 ARM_2D_PFB_DEPEND_ON_NAVIGATION = _BV(5), //!< On Drawing Navigation Event
517};
518
519/*!
520 * \brief The PFB Helper Service Dependency
521 *
522 */
524 //! event handler for low level rendering
526
527 //! event handler for drawing GUI
528 arm_2d_helper_draw_evt_t evtOnDrawing;
529
530 //! low level rendering handler wants to sync-up (return arm_fsm_rt_wait_for_obj)
532
533 //! event handler for each frame complete
535
536 //! event handler for drawing GUI
537 struct {
538 arm_2d_helper_draw_evt_t evtOnDrawing;
539 arm_2d_region_list_item_t *ptDirtyRegion;
541
543
544/*!
545 * \brief PFB Helper configuration
546 *
547 */
549
550 arm_2d_region_t tDisplayArea; //!< screen description
551
552 struct {
553 arm_2d_pfb_t *ptPFBs; //!< PFB blocks for the internal PFB pool
554 arm_2d_size_t tFrameSize; //!< the size of the frame
555 uint32_t wBufferSize; //!< the buffer size
556 uint16_t hwPFBNum; //!< the number of PFB
557 uint16_t bDoNOTUpdateDefaultFrameBuffer : 1; //!< A flag to disable automatically default-framebuffer-registration
558 uint16_t bDisableDynamicFPBSize : 1; //!< A flag to disable resize of the PFB block
559 uint16_t bSwapRGB16 : 1; //!< A flag to enable swapping high and low bytes of an RGB16 pixel
560 uint16_t bDebugDirtyRegions : 1; //!< A flag to show dirty regions on screen for debug
561 uint16_t : 2;
562 uint16_t u3PixelWidthAlign : 3; //!< Pixel alignment in Width for dirty region (2^n)
563 uint16_t u3PixelHeightAlign : 3; //!< Pixel alignment in Height for dirty region (2^n)
564 uint16_t u4PoolReserve : 4; //!< reserve specific number of PFB for other helper services
565
566 } FrameBuffer; //!< frame buffer context
567
568 struct {
569 arm_2d_region_list_item_t *ptRegions; //!< dirty region list item for internal pool
570 uint8_t chCount; //!< number of dirty region list items
571 } DirtyRegion;
572
573 arm_2d_helper_pfb_dependency_t Dependency; //!< user registered dependency
574
576
577/*!
578 * \brief the type of perf counter
579 *
580 */
581typedef enum {
582 ARM_2D_PERFC_RENDER = 0,
583 ARM_2D_PERFC_DRIVER,
584
585 __ARM_2D_PERFC_COUNT,
587
588/*!
589 * \brief the PFB helper control block
590 *
591 */
593
594ARM_PRIVATE(
595 arm_2d_helper_pfb_cfg_t tCFG; //!< user configuration
596
597 struct {
598 arm_2d_region_t tDrawRegion;
599 arm_2d_region_t tTargetRegion;
600
601 arm_2d_region_list_item_t *ptDirtyRegion;
602
603 struct {
604 arm_2d_region_list_item_t *ptWorkingList;
605 arm_2d_region_list_item_t *ptOriginalList;
606 arm_2d_region_list_item_t *ptCandidateList;
607 arm_2d_region_list_item_t *ptFreeList;
608 arm_2d_region_list_item_t tWorkingItem;
609 int16_t iFreeCount;
610 } OptimizedDirtyRegions;
611
612 arm_2d_tile_t tPFBTile;
613 arm_2d_size_t tFrameSize;
614 uint32_t wPFBPixelCount;
615
616 uint8_t chPT;
617 uint8_t chFreePFBCount;
618 struct {
619 uint16_t bIsDirtyRegionOptimizationEnabled : 1;
620 uint16_t bEnableDirtyRegionOptimizationRequest : 1;
621 uint16_t bDisableDirtyRegionOptimizationRequest : 1;
622 uint16_t bEncounterDynamicDirtyRegion : 1;
623 uint16_t bFailedToOptimizeDirtyRegion : 1;
624 uint16_t bIsUsingOptimizedDirtyRegionList : 1;
625 uint16_t : 2;
626
627 uint16_t bIsNewFrame : 1;
628 uint16_t : 1;
629 uint16_t bIgnoreLowLevelFlush : 1;
630 uint16_t bHideNavigationLayer : 1;
631 uint16_t bIsDryRun : 1; //!< A flag to indicate whether the first iteration was a dry run
632 uint16_t bNoAdditionalDirtyRegionList : 1;
633 uint16_t bFirstIteration : 1;
634 uint16_t bIsRegionChanged : 1;
635 };
636
637
638 uintptr_t pFPBPoolAvailable;
639 arm_2d_pfb_t *ptCurrent;
640 arm_2d_pfb_t *ptFreeList;
641 arm_2d_pfb_t *ptFlushing;
642 struct {
643 arm_2d_pfb_t *ptHead;
644 arm_2d_pfb_t *ptTail;
645 }FlushFIFO;
646 arm_2d_tile_t *ptFrameBuffer;
647 } Adapter;
649
650 struct {
651 int64_t lTimestamp; //!< PLEASE DO NOT USE
652 int32_t nTotalCycle; //!< cycles used by drawing
653 int32_t nRenderingCycle; //!< cycles used in LCD flushing
654 } Statistics; //!< performance statistics
655
656};
657
658/*!
659 * \brief the Transform helper control block
660 *
661 */
662typedef struct {
663
664 float fAngle;
665 float fScale;
666
667ARM_PRIVATE(
668 arm_2d_region_list_item_t tDirtyRegions[2];
669 arm_2d_op_t *ptTransformOP;
670 arm_2d_region_list_item_t **ppDirtyRegionList;
671
672 struct {
673 float fValue;
674 float fStep;
675 } Angle;
676
677 struct {
678 float fValue;
679 float fStep;
680 } Scale;
681
682 bool bNeedUpdate;
684
686
687/*============================ GLOBAL VARIABLES ==============================*/
688/*============================ LOCAL VARIABLES ===============================*/
689/*============================ PROTOTYPES ====================================*/
690
691/*!
692 * \brief initialize pfb helper service
693 * \param[in] ptThis the pfb helper control block
694 * \param[in] ptCFG the configuration
695 * \return arm_2d_err_t the process result
696 */
697extern
698ARM_NONNULL(1,2)
701/*!
702 * \brief uninitialize pfb helper service
703 * \param[in] ptThis the pfb helper control block
704 * \return none
705 */
706extern
707ARM_NONNULL(1)
709
710/*!
711 * \brief get the display (screen) region
712 * \param[in] ptThis the pfb helper control block
713 * \return arm_2d_region_t the screen region
714 */
715extern
716ARM_NONNULL(1)
718
719/*!
720 * \brief get the absolute location for a given location on the target tile canvas
721 * \param[in] ptTile the target tile
722 * \param[in] tLocation the location on the target tile canvas
723 * \return arm_2d_location_t the absolute location on a (virtual) screen or on
724 * a root tile canvas
725 */
726extern
727ARM_NONNULL(1)
729 arm_2d_tile_t *ptTile,
730 arm_2d_location_t tLocation);
731
732/*!
733 * \brief get the inital PFB size
734 * \param[in] ptThis the pfb helper control block
735 * \return arm_2d_size_t the PFB size
736 */
737extern
738ARM_NONNULL(1)
740
741/*!
742 * \brief the task function for pfb helper
743 * \param[in] ptThis an initialised PFB helper control block
744 * \param[in] ptDirtyRegions a region list pending for refresh, NULL means
745 * refreshing the whole screen
746 * \retval arm_fsm_rt_cpl complete refreshing one frame
747 * \retval arm_fsm_rt_on_going the refreshing work is on-going
748 * \retval arm_fsm_rt_wait_for_obj user's OnDrawing event handler wants to wait
749 * for some objects, e.g. semaphore etc.
750 * \retval <0 An error is detected
751 */
752extern
753ARM_NONNULL(1)
755 arm_2d_region_list_item_t *ptDirtyRegions);
756
757/*!
758 * \brief flush the FPB FIFO
759 * \note This function is THREAD-SAFE
760 * \note For normal usage, please DO NOT use this function unless you know what
761 * you are doing.
762 * \param[in] ptThis an initialised PFB helper control block
763 */
764extern
765ARM_NONNULL(1)
767
768/*!
769 * \brief hide the navigation layer
770 * \param[in] ptThis an initialised PFB helper control block
771 */
772extern
773ARM_NONNULL(1)
775
776/*!
777 * \brief show the navigation layer if there is a valid one
778 * \param[in] ptThis an initialised PFB helper control block
779 */
780extern
781ARM_NONNULL(1)
783
784
785/*!
786 * \brief ignore the low level PFB flushing only
787 * \param[in] ptThis an initialised PFB helper control block
788 */
789extern
790ARM_NONNULL(1)
792
793/*!
794 * \brief resume the low level PFB flushing
795 * \param[in] ptThis an initialised PFB helper control block
796 */
797extern
798ARM_NONNULL(1)
800
801
802/*!
803 * \brief update PFB dependency (event handlers)
804 * \param[in] ptThis the PFB helper control block
805 * \param[in] chMask the bit mask for event handlers
806 * \param[in] ptDependency the new dependency description
807 * \return arm_2d_err_t the process result
808 */
809extern
810ARM_NONNULL(1,3)
812 arm_2d_helper_pfb_t *ptThis,
813 uint_fast8_t chMask,
814 const arm_2d_helper_pfb_dependency_t *ptDependency);
815
816/*!
817 * \brief tell PFB helper that a low level LCD flushing work is complete
818 * \note This function is THREAD-SAFE, You can call this function asynchronously,
819 * e.g.
820 * - A ISR to indicate DMA-transfer complete event or
821 * - A different Thread
822 * \param[in] ptThis the PFB helper control block
823 * \param[in] ptPFB the used PFB block
824 */
825extern
826ARM_NONNULL(1)
828 arm_2d_pfb_t *ptPFB);
829
830/*!
831 * \brief swap the high and low bytes for each rgb16 pixel
832 *
833 * \param[in] phwBuffer the pixel buffer
834 * \note the phwBuffer MUST aligned to half-word addresses
835 *
836 * \param[in] wSize the number of pixels
837 */
838extern
839void arm_2d_helper_swap_rgb16(uint16_t *phwBuffer, uint32_t wCount);
840
841/*!
842 * \brief try to get a PFB block from the pool
843 * \param[in] ptThis the PFB helper control block
844 * \retval NULL the pool is empty
845 * \retval !NULL a valid pfb block
846 */
847extern
848ARM_NONNULL(1)
850
851/*!
852 * \brief free a PFB block to the pool
853 * \param[in] ptThis the PFB helper control block
854 * \param[in] ptPFB the target PFB block
855 */
856extern
857ARM_NONNULL(1)
859
860/*!
861 * \brief enable dirty region optimization service
862 * \param[in] ptThis the PFB helper control block
863 * \param[in] ptRegions an optional array of dirty region items, which will be
864 * added to the dirty region item pool. NULL is acceptable.
865 * \param[in] chCount the number of items in the array.
866 */
867extern
868ARM_NONNULL(1)
870 arm_2d_helper_pfb_t *ptThis,
871 arm_2d_region_list_item_t *ptRegions,
872 uint_fast8_t chCount);
873/*!
874 * \brief disable dirty region optimization service
875 * \param[in] ptThis the PFB helper control block
876 */
877extern
878ARM_NONNULL(1)
880 arm_2d_helper_pfb_t *ptThis);
881
882/*!
883 * \brief initialize a given transform helper
884 * \param[in] ptThis the target helper
885 * \param[in] ptTransformOP the target transform OP, NULL is not accepted.
886 * \param[in] fAngleStep the minimal acceptable angle change.
887 * \param[in] fScaleStep the minimal acceptable scale ratio change.
888 * \param[in] ppDirtyRegionList the address of the dirty region list
889 */
890extern
891ARM_NONNULL(1,2,5)
893 arm_2d_op_t *ptTransformOP,
894 float fAngleStep,
895 float fScaleStep,
896 arm_2d_region_list_item_t **ppDirtyRegionList);
897
898/*!
899 * \brief depose a given transform helper
900 * \param[in] ptThis the target helper
901 */
902extern
903ARM_NONNULL(1)
905
906/*!
907 * \brief the on-frame-begin event handler for a given transform helper
908 * \param[in] ptThis the target helper
909 * \note Usually this event handler should be insert the frame start event
910 * handler of a target scene.
911 */
912extern
913ARM_NONNULL(1)
915
916/*!
917 * \brief force transform helper to update dirty region
918 *
919 * \note sometimes, we want to force transform helper to update dirty regions
920 * even if both the angel and scale keep the same, for example, the pivots
921 * are updated.
922 * \param[in] ptThis the target helper
923 */
924extern
925ARM_NONNULL(1)
927
928/*!
929 * \brief update a given transform helper with new values
930 * \param[in] ptThis the target helper
931 * \param[in] fAngle the new angle value
932 * \param[in] fScale the new scale ratio
933 * \note The new value is only accepted when the change between the old value
934 * and the new value is larger than the minimal acceptable mount.
935 */
936extern
937ARM_NONNULL(1)
939 float fAngle,
940 float fScale);
941
942/*!
943 * \brief update the dirty region after a transform operation
944 * \param[in] ptThis the target helper
945 * \param[in] ptCanvas the canvas
946 * \param[in] bIsNewFrame whether this is a new frame
947 */
948extern
949ARM_NONNULL(1)
952 const arm_2d_region_t *ptCanvas,
953 bool bIsNewFrame);
954
955
956/*!
957 * \brief initialize the 3FB (direct mode) service
958 * \param[in] ptThis the helper service control block
959 * \param[in] ptCFG the configuration structure
960 */
961extern
962ARM_NONNULL(1,2)
964 const arm_2d_helper_3fb_cfg_t *ptCFG);
965
966
967/*!
968 * \brief report the copy-completion event to the 3FB (direct mode) service
969 * \note see function __arm_2d_helper_3fb_dma_copy for details
970 * \param[in] ptThis the helper service control block
971 */
972extern
973ARM_NONNULL(1)
975
976/*!
977 * \brief get a pointer for flushing
978 * \param[in] ptThis the helper service control block
979 * \return void * the address of a framebuffer
980 *
981 * \note please only call this function when on vsync event.
982 */
983extern
984ARM_NONNULL(1)
986
987/*!
988 * \brief please do NOT use this function. It is used by the display adapter.
989 */
990extern
991ARM_NONNULL(1,2)
993 const arm_2d_pfb_t *ptPFB);
994
995
996
997/*! @} */
998
999#if defined(__clang__)
1000# pragma clang diagnostic pop
1001#endif
1002
1003#ifdef __cplusplus
1004}
1005#endif
1006
1007
1008
1009#endif