Arm-2D  
2D Image Processing Library for Cortex-M Processors
 
Loading...
Searching...
No Matches
arm_2d_helper_pfb.h
1/*
2 * Copyright (C) 2024 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: 21. April 2025
25 * $Revision: V.2.0.0
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#include <stdint.h>
38
39#ifdef __cplusplus
40extern "C" {
41#endif
42
43
44#if defined(__clang__)
45# pragma clang diagnostic push
46# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
47# pragma clang diagnostic ignored "-Wmissing-declarations"
48# pragma clang diagnostic ignored "-Wpadded"
49#endif
50
51/* OOC header, please DO NOT modify */
52#ifdef __ARM_2D_HELPER_PFB_IMPLEMENT__
53# define __ARM_2D_IMPL__
54# undef __ARM_2D_HELPER_PFB_IMPLEMENT__
55#elif defined(__ARM_2D_HELPER_PFB_INHERIT__)
56# undef __ARM_2D_HELPER_PFB_INHERIT__
57# define __ARM_2D_INHERIT__
58#endif
59#include "arm_2d_utils.h"
60
61/*!
62 * \addtogroup gHelper 8 Helper Services
63 * @{
64 */
65
66/*============================ MACROS ========================================*/
67
68#define ARM_2D_FPS_MODE_RENDER_ONLY 0
69#define ARM_2D_FPS_MODE_REAL 1
70
71/*============================ MACROFIED FUNCTIONS ===========================*/
72
73/*!
74 * \brief a macro wrapper in uppercase to help initialising PFB service
75 * \param[in] __CB_ADDR the address of the arm_2d_helper_pfb_t object
76 * \param[in] __SCREEN_WIDTH the width of the screen
77 * \param[in] __SCREEN_HEIGHT the hight of the screen
78 * \param[in] __PIXEL_TYPE the integer type of the pixel, i.e. uint8_t, uint16_t,
79 * uint32_t
80 * \param[in] __COLOUR_FORMAT the screen colour format, i.e. ARM_2D_COLOUR_CCCN888,
81 * ARM_2D_COLOUR_RGB565 etc.
82 * \param[in] __WIDTH the width of the PFB block
83 * \param[in] __HEIGHT the height of the PFB block
84 * \note For the same number of pixels in a PFB block, please priority the width
85 * over height, for example, 240 * 1 is better than 30 * 8
86 * \param[in] __PFB_NUM the number of PFB blocks in the built-in PFB pool.
87 * \param[in] ... a code block to add additional initializer, see example below:
88 * \return arm_2d_err_t the result of the initialisation process
89 *
90 * \code {.c}
91
92 static ARM_NOINIT arm_2d_helper_pfb_t s_tExamplePFB;
93 ...
94 // initialise FPB helper
95 if (ARM_2D_HELPER_PFB_INIT(
96 &s_tExamplePFB, // FPB Helper object
97 __GLCD_CFG_SCEEN_WIDTH__, // screen width
98 __GLCD_CFG_SCEEN_HEIGHT__, // screen height
99 uint16_t, // colour date type
100 ARM_2D_COLOUR_RGB565, // colour format
101 240, // PFB block width
102 1, // PFB block height
103 1, // number of PFB in the PFB pool
104 {
105 .evtOnLowLevelRendering = {
106 // callback for low level rendering
107 .fnHandler = &__pfb_render_handler,
108 },
109 .evtOnDrawing = {
110 // callback for drawing GUI
111 .fnHandler = &__pfb_draw_background_handler,
112 },
113 },
114 //.FrameBuffer.bSwapRGB16 = true,
115 ) < 0) {
116 //! error detected
117 assert(false);
118 }
119 * \endcode
120 *
121 */
122#define ARM_2D_HELPER_PFB_INIT( __CB_ADDR, /* PFB Helper object address */ \
123 __SCREEN_WIDTH, /* Screen width */ \
124 __SCREEN_HEIGHT,/* Screen height */ \
125 __PIXEL_TYPE, /* The type of the pixels */ \
126 __COLOUR_FORMAT,/* the colour format */ \
127 __PFB_WIDTH, /* The width of the PFB block */\
128 __PFB_HEIGHT, /* The height of the PFB block*/\
129 __PFB_NUM, /* Block count in the PFB pool*/\
130 ... /* Event Handler */ \
131 ) \
132 ({ \
133 ARM_SECTION(".bss.noinit.arm_2d_pfb_pool") \
134 static struct { \
135 arm_2d_pfb_t tFPB; \
136 __ALIGNED(4) \
137 __PIXEL_TYPE tBuffer[(__PFB_WIDTH) * (__PFB_HEIGHT)]; \
138 } s_tPFBs[__PFB_NUM]; \
139 \
140 arm_2d_helper_pfb_cfg_t tCFG = { \
141 .tDisplayArea.tSize = { \
142 .iWidth = (__SCREEN_WIDTH), \
143 .iHeight = (__SCREEN_HEIGHT), \
144 }, \
145 \
146 .FrameBuffer.ptPFBs = (arm_2d_pfb_t *)s_tPFBs, \
147 .FrameBuffer.tFrameSize = { \
148 .iWidth = (__PFB_WIDTH), \
149 .iHeight = (__PFB_HEIGHT), \
150 }, \
151 .FrameBuffer.u24BufferSize = sizeof(s_tPFBs[0].tBuffer), \
152 .FrameBuffer.u7ColourFormat = (__COLOUR_FORMAT), \
153 .FrameBuffer.u8PFBNum = dimof(s_tPFBs), \
154 .Dependency = \
155 __VA_ARGS__ \
156 }; \
157 \
158 arm_2d_helper_pfb_init((__CB_ADDR), &tCFG); \
159 })
160
161/*!
162 * \brief a macro wrapper to update the evtOnDrawring event handler
163 * \param[in] __CB_ADDR the address of the arm_2d_helper_pfb_t object
164 * \param[in] __HANDLER the new handler
165 * \param[in] ... [Optional] an address (of user defined structure) passed to the
166 * event handler.
167 * \return arm_2d_err_t the process result
168 */
169#define ARM_2D_HELPER_PFB_UPDATE_ON_DRAW_HANDLER( \
170 __CB_ADDR, /* PFB Helper object address */ \
171 __HANDLER, /* new on-draw-handler function*/\
172 ...) /* An optional target address */ \
173 arm_2d_helper_pfb_update_dependency((__CB_ADDR), \
174 ARM_2D_PFB_DEPEND_ON_DRAWING, \
175 (arm_2d_helper_pfb_dependency_t []) {{ \
176 .evtOnDrawing = { \
177 .fnHandler = (__HANDLER), \
178 .pTarget = (NULL,##__VA_ARGS__),\
179 }, \
180 }})
181
182
183#define __IMPL_ARM_2D_REGION_LIST(__NAME, ...) \
184 enum { \
185 __NAME##_offset = __COUNTER__, \
186 }; \
187 __VA_ARGS__ \
188 arm_2d_region_list_item_t __NAME[] = {
189
190
191#define IMPL_ARM_2D_REGION_LIST(__NAME, ...) \
192 __IMPL_ARM_2D_REGION_LIST(__NAME,##__VA_ARGS__)
193
194
195#define END_IMPL_ARM_2D_REGION_LIST(...) \
196 }; \
197 /* In ANSI-C Standard, the local variable always hides a global */ \
198 /* of the same name as soon as it's declared. We use this feature */\
199 /* to provide a temporary fix for backward compatibility.*/ \
200 /* the following line should be removed in the future */ \
201 static const arm_2d_tile_t * const ptCurrentTile = NULL;
202
203#define __ADD_REGION_TO_LIST(__NAME, ...) \
204 { \
205 .ptNext = (arm_2d_region_list_item_t *) \
206 &(__NAME[__COUNTER__ - __NAME##_offset]), \
207 .tRegion = { \
208 __VA_ARGS__ \
209 }, \
210 }
211
212#define ADD_REGION_TO_LIST(__NAME, ...) \
213 __ADD_REGION_TO_LIST(__NAME, ##__VA_ARGS__)
214
215
216#define __ADD_LAST_REGION_TO_LIST(__NAME, ...) \
217 { \
218 .ptNext = NULL, \
219 .tRegion = { \
220 __VA_ARGS__ \
221 }, \
222 }
223
224#define ADD_LAST_REGION_TO_LIST(__NAME, ...) \
225 __ADD_LAST_REGION_TO_LIST(__NAME, ##__VA_ARGS__)
226
227
228#define IMPL_PFB_ON_DRAW(__NAME) IMPL_ON_DRAW_EVT(__NAME)
229
230
231#define IMPL_PFB_ON_LOW_LV_RENDERING(__NAME) \
232 void __NAME(void *pTarget, \
233 const arm_2d_pfb_t *ptPFB, \
234 bool bIsNewFrame)
235
236
237#define IMPL_PFB_ON_FRAME_SYNC_UP(__NAME) \
238 bool __NAME(void *pTarget)
239
240#define IMPL_PFB_BEFORE_FLUSHING(__NAME) \
241 bool __NAME(void *pTarget, \
242 arm_2d_pfb_t *ptOrigin, \
243 arm_2d_pfb_t *ptScratch)
244
245
246/*!
247 * \brief a macro wrapper in lowercase to help initialising PFB service
248 * \param[in] __CB_ADDR the address of the arm_2d_helper_pfb_t object
249 * \param[in] __SCREEN_WIDTH the width of the screen
250 * \param[in] __SCREEN_HEIGHT the hight of the screen
251 * \param[in] __PIXEL_TYPE the integer type of the pixel, i.e. uint8_t, uint16_t,
252 * uint32_t
253 * \param[in] __COLOUR_FORMAT the screen colour format, i.e. ARM_2D_COLOUR_CCCN888,
254 * ARM_2D_COLOUR_RGB565 etc.
255 * \param[in] __WIDTH the width of the PFB block
256 * \param[in] __HEIGHT the height of the PFB block
257 * \note For the same number of pixels in a PFB block, please priority the width
258 * over height, for example, 240 * 1 is better than 30 * 8
259 * \param[in] __PFB_NUM the number of PFB blocks in the built-in PFB pool.
260 * \param[in] ... a code block to add additional initializer, see example below:
261 * \return arm_2d_err_t the result of the initialisation process
262 *
263 * \code {.c}
264
265 static ARM_NOINIT arm_2d_helper_pfb_t s_tExamplePFB;
266 ...
267 // initialise FPB helper
268 if (init_arm_2d_helper_pfb(
269 &s_tExamplePFB, // FPB Helper object
270 __GLCD_CFG_SCEEN_WIDTH__, // screen width
271 __GLCD_CFG_SCEEN_HEIGHT__, // screen height
272 uint16_t, // colour date type
273 ARM_2D_COLOUR_RGB565, // colour format
274 240, // PFB block width
275 1, // PFB block height
276 1, // number of PFB in the PFB pool
277 {
278 .evtOnLowLevelRendering = {
279 // callback for low level rendering
280 .fnHandler = &__pfb_render_handler,
281 },
282 .evtOnDrawing = {
283 // callback for drawing GUI
284 .fnHandler = &__pfb_draw_background_handler,
285 },
286 },
287 //.FrameBuffer.bSwapRGB16 = true,
288 ) < 0) {
289 //! error detected
290 assert(false);
291 }
292 * \endcode
293 *
294 */
295#define init_arm_2d_helper_pfb( __CB_ADDR, \
296 __SCREEN_WIDTH, \
297 __SCREEN_HEIGHT, \
298 __PIXEL_TYPE, \
299 __COLOUR_FORMAT, \
300 __WIDTH, \
301 __HEIGHT, \
302 __PFB_NUM, \
303 ... \
304 ) \
305 ARM_2D_HELPER_PFB_INIT( \
306 __CB_ADDR, \
307 __SCREEN_WIDTH, \
308 __SCREEN_HEIGHT, \
309 __PIXEL_TYPE, \
310 __COLOUR_FORMAT, \
311 __WIDTH, \
312 __HEIGHT, \
313 __PFB_NUM, \
314 ##__VA_ARGS__ \
315 )
316
317/*!
318 * \brief a macro wrapper to update the evtOnDrawring event handler
319 * \param[in] __CB_ADDR the address of the arm_2d_helper_pfb_t object
320 * \param[in] __HANDLER the new handler
321 * \param[in] ... [Optional] an address (of user defined structure) passed to the
322 * event handler.
323 * \return arm_2d_err_t the process result
324 */
325#define update_arm_2d_helper_pfb_on_draw_handler( \
326 __CB_ADDR, /* PFB Helper object address */ \
327 __HANDLER, /* new on-draw-handler function*/\
328 ...) /* An optional target address */ \
329 ARM_2D_HELPER_PFB_UPDATE_ON_DRAW_HANDLER( \
330 (__CB_ADDR), \
331 (__HANDLER),##__VA_ARGRS__)
332
333/*!
334 * \brief tell PFB helper that a low level LCD flushing work is complete
335 * \note This function is THREAD-SAFE, You can call this function asynchronously,
336 * e.g.
337 * - A ISR to indicate DMA-transfer complete event or
338 * - A different Thread
339 * \param[in] ptThis the PFB helper control block
340 * \param[in] ... the used PFB block.
341 * \note please do not use this parameter, it is only kept for backward
342 * compatability.
343 */
344#define arm_2d_helper_pfb_report_rendering_complete(__PFB_HELPER_PTR,...) \
345 __arm_2d_helper_pfb_report_rendering_complete((__PFB_HELPER_PTR), \
346 (NULL,##__VA_ARGS__))
347
348
349#define __arm_2d_helper_dirty_region_update_dirty_regions0 \
350 __arm_2d_helper_dirty_region_update_dirty_regions
351
352/*!
353 * \brief update a specified new region while erase the previous region
354 *
355 * \param[in] ptThis the target helper
356 * \param[in] ptTargetTile the target tile to draw content
357 * \param[in] ptVisibleArea a visible region in the target tile used to clip
358 * the ptNewRegion, NULL means no clipping.
359 * \param[in] ptNewRegion the new region to update, NULL means nothing
360 * to update
361 * \param[in] bIsNewFrame unused, keep for backward compatibility
362 */
363#define __arm_2d_helper_dirty_region_update_dirty_regions3( __helper_ptr, \
364 __tile_ptr, \
365 __visible_area_ptr, \
366 __new_region_ptr, \
367 __is_new_frame) \
368 __arm_2d_helper_dirty_region_update_dirty_regions2( \
369 (__helper_ptr), \
370 (__tile_ptr), \
371 (__visible_area_ptr), \
372 (__new_region_ptr))
373
374/*!
375 * \brief update a specified new region while erase the previous region
376 *
377 * \param[in] ptThis the target helper
378 * \param[in] ptTargetTile the target tile to draw content
379 * \param[in] ptNewRegion the new region to update, NULL means nothing
380 * to update
381 */
382#define __arm_2d_helper_dirty_region_update_dirty_regions1( __helper_ptr, \
383 __tile_ptr, \
384 __new_region_ptr) \
385 __arm_2d_helper_dirty_region_update_dirty_regions2( \
386 (__helper_ptr), \
387 (__tile_ptr), \
388 NULL, \
389 (__new_region_ptr))
390
391
392/*!
393 * \brief update a specified new region while erase the previous region
394 *
395 * \param[in] __helper_ptr the target helper
396 * \param[in] __tile_ptr the target tile to draw content
397 * \param[in] ... optional parameters, and the following combinations are valid:
398 * a. new region ptr
399 * b. the canvas ptr and the new region ptr
400 * c. the canvas ptr, the new region ptr and a reserved option
401 * (bIsNewFrame)
402 */
403#define arm_2d_helper_dirty_region_update_dirty_regions( __helper_ptr, \
404 __tile_ptr, \
405 ...) \
406 ARM_CONNECT2(__arm_2d_helper_dirty_region_update_dirty_regions, \
407 __ARM_VA_NUM_ARGS(__VA_ARGS__))((__helper_ptr), \
408 (__tile_ptr) \
409 ,##__VA_ARGS__)
410
411/*!
412 * \brief update a specified new region while erase the previous region
413 *
414 * \param[in] __item_ptr the target region item
415 * \param[in] __target_tile_ptr the target tile to draw content
416 * \param[in] __visible_region_ptr a visible region in the target tile used to clip
417 * the ptNewRegion, NULL means no clipping.
418 * \param[in] __new_region_ptr the new region to update, NULL means nothing
419 * to update
420 */
421#define __arm_2d_helper_dirty_region_update_item4( __item_ptr, \
422 __target_tile_ptr, \
423 __visible_region_ptr, \
424 __new_region_ptr) \
425 __arm_2d_helper_dirty_region_item_update((__item_ptr), \
426 (__target_tile_ptr), \
427 (__visible_region_ptr), \
428 (__new_region_ptr))
429
430/*!
431 * \brief deprecated
432 *
433 */
434#define __arm_2d_helper_dirty_region_update_item5( __dirty_region_helper_ptr, \
435 __item_ptr, \
436 __target_tile_ptr, \
437 __visible_region_ptr, \
438 __new_region_ptr) \
439 __arm_2d_helper_dirty_region_item_update((__item_ptr), \
440 (__target_tile_ptr), \
441 (__visible_region_ptr), \
442 (__new_region_ptr))
443
444#define arm_2d_helper_dirty_region_update_item(...) \
445 ARM_CONNECT2( __arm_2d_helper_dirty_region_update_item, \
446 __ARM_VA_NUM_ARGS(__VA_ARGS__) \
447 )(__VA_ARGS__)
448
449
450#define arm_2d_helper_pfb_is_region_active( __target_tile_ptr, \
451 __target_region_ptr, \
452 __consider_dry_run, \
453 ...) \
454 ARM_CONNECT2( __arm_2d_helper_pfb_is_region_active, \
455 __ARM_VA_NUM_ARGS(__VA_ARGS__))( \
456 (__target_tile_ptr), \
457 (__target_region_ptr), \
458 (__consider_dry_run),##__VA_ARGS__)
459
460#define arm_2d_helper_dirty_region_transform_update_value( __HELPER_PTR, \
461 __ANGLE, \
462 __SCALE, \
463 ...) \
464 ARM_CONNECT2( __arm_2d_helper_dirty_region_transform_update_value,\
465 __ARM_VA_NUM_ARGS(__VA_ARGS__))((__HELPER_PTR), \
466 (__ANGLE), \
467 __SCALE, \
468 ##__VA_ARGS__)
469
470#define impl_arm_2d_region_list(__NAME, ...) \
471 IMPL_ARM_2D_REGION_LIST(__NAME,##__VA_ARGS__)
472#define add_region_to_list(__NAME, ...) \
473 ADD_REGION_TO_LIST(__NAME, ##__VA_ARGS__)
474#define add_last_region_to_list(__NAME, ...) \
475 ADD_LAST_REGION_TO_LIST(__NAME, ##__VA_ARGS__)
476#define end_impl_arm_2d_region_list(...) \
477 END_IMPL_ARM_2D_REGION_LIST(__VA_ARGS__)
478
479#define impl_pfb_on_draw(__NAME) IMPL_PFB_ON_DRAW(__NAME)
480#define impl_pfb_on_low_lv_rendering(__NAME) \
481 IMPL_PFB_ON_LOW_LV_RENDERING(__NAME)
482
483/*============================ TYPES =========================================*/
484
485/*!
486 * \brief direct mode helper service frame-buffer control block states
487 *
488 * \note state transition diagram
489 * <<< service initialization >>>
490 * |
491 * ARM_3FB_STATE_READY_FOR_FLUSH <------+
492 * | |
493 * ARM_3FB_STATE_FLUSHING |
494 * | |
495 * ARM_3FB_STATUS_UNUSED ---> ARM_3FB_STATE_READY_TO_DRAW |
496 * | |
497 * ARM_3FB_STATE_COPYING_AS_TARGET |
498 * |
499 * ARM_3FB_STATE_DRAWING |
500 * | |
501 * ARM_3FB_STATE_COPYING_AS_SOURCE -----+
502 *
503 */
504enum {
505 ARM_3FB_STATE_UNUSED = 0, //!< the FB hasn't been used
506 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)
507 ARM_3FB_STATE_READY_TO_DRAW, //!< the FB is ready to draw, the previous state is ARM_3FB_STATE_COPYING_AS_TARGET
508 ARM_3FB_STATE_DRAWING, //!< the FB is used for drawing, the previous state is ARM_3FB_STATE_READY_TO_DRAW
509 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
510 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
511 ARM_3FB_STATE_FLUSHING, //!< the FB is used for flushing, the previous state is ARM_3FB_STATE_READY_FOR_FLUSH
512};
513
515
516/*!
517 * \brief An interface for 2D-Copy.
518 * \param[in] pnSource the source image address
519 * \param[in] wSourceStride the stride of the source image
520 * \param[in] pnTarget the address in the target framebuffer
521 * \param[in] wTargetStride the stride of the target framebuffer
522 * \param[in] iWidth the safe width of the source image
523 * \param[in] iHeight the safe height of the source image
524 * \retval true the 2D copy is complete when leaving this function
525 * \retval false An async 2D copy request is sent to the DMA
526 */
527typedef
529 void *pObj,
530 uintptr_t pnSource,
531 uint32_t wSourceStride,
532 uintptr_t pnTarget,
533 uint32_t wTargetStride,
534 int16_t iWidth,
535 int16_t iHeight,
536 uint_fast8_t chBytePerPixel );
537
540 void *pObj;
542
543/*!
544 * \brief An interface for DMA memory-to-memory copy.
545 * If you have a DMA, you can implement this function by using
546 * __OVERRIDE_WEAK.
547 * You should implement an ISR for copy-complete event and call
548 * arm_2d_helper_3fb_report_dma_copy_complete() to notify the
549 * 3FB (direct mode) helper service.
550 *
551 * \param[in] ptThis the helper service control block
552 * \param[in] pObj the address of the user object
553 * \param[in] pnSource the source address of the memory block
554 * \param[in] pnTarget the target address
555 * \param[in] nDataItemCount the number of date items
556 * \param[in] chDataItemSize the size of each data item
557 */
558typedef
560 void *pObj,
561 uintptr_t pnSource,
562 uintptr_t pnTarget,
563 uint32_t nDataItemCount,
564 uint_fast8_t chDataItemSize);
565
568 void *pObj;
570
571/*!
572 * \brief configuration structure for the 3fb (direct mode) helper service
573 */
575 arm_2d_size_t tScreenSize; //!< the screen size
576 uint8_t chPixelBits; //!< the number of bits in one pixel
577 uintptr_t pnAddress[3]; //!< addresses of the 3 full-frame-buffer
578
579 arm_2d_helper_2d_copy_evt_t evtOn2DCopy;
580 arm_2d_helper_dma_copy_evt_t evtOnDMACopy;
582
583#define ARM_2D_3FB_INVALID_IDX 3
584
585/*!
586 * \brief the control block of the 3FB (direct mode) service
587 */
588typedef struct arm_2d_helper_3fb_t {
589ARM_PRIVATE(
591
592 struct {
593 uint8_t u2Drawing : 2; //!< FB pointer for drawing
594 uint8_t u2Flushing : 2; //!< FB pointer for flushing
595 uint8_t u2ReadyToFlush : 2; //!< FB pointer of ready to flush
596 uint8_t u2ReadyToDraw : 2; //!< FB pointer of ready to draw
597 uint8_t tState[3];
598 uintptr_t tSemaphore; //!< semaphore for async access
599 bool bFBCopyComplete; //!< a flag to indicate the completion of a DMA copy
600 } Runtime;
603
605
606/*!
607 * \brief the header of a PFB block
608 */
609typedef struct arm_2d_pfb_t {
610 struct arm_2d_pfb_t *ptNext; //!< next pfb block
611 arm_2d_helper_pfb_t *ptPFBHelper; //!< the pfb helper service current PFB block comes from
612 arm_2d_tile_t tTile; //!< descriptor
613 uint32_t u24Size : 24;
614 uint32_t u7ColourFormat : 7; //!< colour format
615 uint32_t bIsNewFrame : 1; //!< a flag to indicate the starting of a frame
617
618/*!
619 * \brief the node of a region list
620 *
621 */
623 struct arm_2d_region_list_item_t *ptNext; //!< the next node
624ARM_PRIVATE(
625 struct arm_2d_region_list_item_t *ptInternalNext; //!< the next node in the internal list
627 arm_2d_region_t tRegion; //!< the region
628
629ARM_PROTECTED(
630 uint8_t chUserRegionIndex; //!< User Region Index, used to indicate updating which dynamic dirty regions
631 uint8_t bIgnore : 1; //!< ignore this region
632 uint8_t bUpdated : 1; //!< this region item has been updated, PFB helper should refresh it again.
633 uint8_t : 6; //!< reserved for the future
634
635 uint16_t bFromInternalPool : 1; //!< a flag indicating whether this list item coming from the internal pool
636 uint16_t bFromHeap : 1; //!< whether this item comes from the HEAP
637 uint16_t u2UpdateState : 2; //!< reserved for internal FSM
638 uint16_t u12KEY : 12; //!< KEY
639)
640
642
643/*!
644 * \brief the On Low Level Rendering event handler for the low level (LCD Driver)
645 *
646 * \param[in] pTarget a user attached target address
647 * \param[in] ptPFB the PFB block
648 * \param[in] bIsNewFrame a flag indicate the starting of a new frame
649 */
651 void *pTarget,
652 const arm_2d_pfb_t *ptPFB,
653 bool bIsNewFrame);
654
655/*!
656 * \brief low level render event
657 */
659 arm_2d_helper_render_handler_t *fnHandler; //!< event handler function
660 void *pTarget; //!< user attached target
662
663/*!
664 * \brief before-flushing event handler
665 * \param[in] ptOrigin the original PFB
666 * \param[in] ptScratch A scratch PFB
667 * \return true the new content is stored in ptScratch
668 * \return false the new content is stored in ptOrigin
669 */
670typedef bool arm_2d_helper_before_flushing_handler_t( void *pTarget,
671 arm_2d_pfb_t *ptOrigin,
672 arm_2d_pfb_t *ptScratch);
673
674/*!
675 * \brief screen rotation event
676 */
679 void *pTarget;
681
682/*!
683 * \brief the enumeration for events
684 *
685 */
686enum {
687 ARM_2D_PFB_DEPEND_ON_LOW_LEVEL_RENDERING = _BV(0), //!< On Low Level Rendering Event
688 ARM_2D_PFB_DEPEND_ON_DRAWING = _BV(1), //!< On Drawing Event
689 ARM_2D_PFB_DEPEND_ON_LOW_LEVEL_SYNC_UP = _BV(2), //!< On Low Level Sync-up Event
690 ARM_2D_PFB_DEPEND_ON_FRAME_SYNC_UP = _BV(3), //!< On Frame Sync-up Event
691 ARM_2D_PFB_DEPEND_ON_EACH_FRAME_CPL = _BV(4), //!< On Each Frame Complete Event
692 ARM_2D_PFB_DEPEND_ON_NAVIGATION = _BV(5), //!< On Drawing Navigation Event
693};
694
695/*!
696 * \brief The PFB Helper Service Dependency
697 *
698 */
700 //! event handler for low level rendering
702
703 //! event handler for drawing GUI
704 arm_2d_helper_draw_evt_t evtOnDrawing;
705
706 /*! event handler for waiting LCD finish rendering previous frame
707 * \note when then handler return false, the refresh task will yield and return
708 * arm_fsm_rt_async.
709 * when the handler return true, it means the display device finished
710 * rendering the previous frame and the refresh task will continue the
711 * following steps.
712 */
714
715 //! event handler for each frame complete
717
718 //! event handler for drawing GUI
719 struct {
720 arm_2d_helper_draw_evt_t evtOnDrawing;
721 arm_2d_region_list_item_t *ptDirtyRegion;
723
724 //! event handler for screen rotation
726
728
729/*!
730 * \brief PFB Helper configuration
731 *
732 */
734
735 arm_2d_region_t tDisplayArea; //!< screen description
736
737 struct {
738 arm_2d_pfb_t *ptPFBs; //!< PFB blocks for the internal PFB pool
739 arm_2d_size_t tFrameSize; //!< the size of the frame
740 uint32_t u24BufferSize : 24; //!< the buffer size
741 uint32_t u7ColourFormat : 7 ; //!< the colour format
742 uint32_t : 1 ; //!< reserved
743 uint32_t u8PFBNum : 8; //!< the number of PFB
744 uint32_t bDoNOTUpdateDefaultFrameBuffer : 1; //!< A flag to disable automatically default-framebuffer-registration
745 uint32_t bDisableDynamicFPBSize : 1; //!< A flag to disable resize of the PFB block
746 uint32_t bSwapRGB16 : 1; //!< A flag to enable swapping high and low bytes of an RGB16 pixel
747 uint32_t bDebugDirtyRegions : 1; //!< A flag to show dirty regions on screen for debug
748 uint32_t : 10;
749 uint32_t u3PixelWidthAlign : 3; //!< Pixel alignment in Width for dirty region (2^n)
750 uint32_t u3PixelHeightAlign : 3; //!< Pixel alignment in Height for dirty region (2^n)
751 uint32_t u4PoolReserve : 4; //!< reserve specific number of PFB for other helper services
752
753 } FrameBuffer; //!< frame buffer context
754
755 struct {
756 arm_2d_region_list_item_t *ptRegions; //!< dirty region list item for internal pool
757 uint8_t chCount; //!< number of dirty region list items
758 } DirtyRegion;
759
760 arm_2d_helper_pfb_dependency_t Dependency; //!< user registered dependency
761
763
764/*!
765 * \brief the type of perf counter
766 *
767 */
768typedef enum {
769 ARM_2D_PERFC_RENDER = 0,
770 ARM_2D_PERFC_DRIVER,
771
772 __ARM_2D_PERFC_COUNT,
774
775typedef enum {
776
777 ARM_2D_PFB_SCAN_POLICY_HORIZONTAL_FIRST = (0 << 0), /* left to right first, then top to down */
778 ARM_2D_PFB_SCAN_POLICY_VERTICAL_FIRST = (1 << 0), /* top to down first, then left to right */
779
780 /* default */
781 ARM_2D_PFB_SCAN_POLICY_NORMAL = 0,
782
783} arm_2d_pfb_scan_policy_t;
784
785/*!
786 * \brief the PFB helper control block
787 *
788 */
790
791ARM_PRIVATE(
792 arm_2d_helper_pfb_cfg_t tCFG; //!< user configuration
793
794 struct {
795 arm_2d_location_t tScanOffset;
796 arm_2d_region_t tTargetRegion;
797
798 arm_2d_region_list_item_t *ptDirtyRegion;
799
800 struct {
801 arm_2d_region_list_item_t *ptWorkingList;
802 arm_2d_region_list_item_t *ptOriginalList;
803 arm_2d_region_list_item_t *ptCandidateList;
804 arm_2d_region_list_item_t *ptFreeList;
805 arm_2d_region_list_item_t tWorkingItem;
806 } OptimizedDirtyRegions;
807
808 arm_2d_tile_t tPFBTile;
809 arm_2d_size_t tFrameSize;
810 uint32_t wPFBPixelCount;
811
812 uint8_t chPT;
813 uint8_t chFreePFBCount;
814 int16_t iDirtyRegionFreeCount;
815
816 struct {
817 uint32_t bIsDirtyRegionOptimizationEnabled : 1;
818 uint32_t bEnableDirtyRegionOptimizationRequest : 1;
819 uint32_t bDisableDirtyRegionOptimizationRequest : 1;
820 uint32_t bEncounterDynamicDirtyRegion : 1;
821 uint32_t bFailedToOptimizeDirtyRegion : 1;
822 uint32_t bIsUsingOptimizedDirtyRegionList : 1;
823 uint32_t bDirtyRegionDebugModeSkipFrame : 1;
824 uint32_t bIngoreLowLevelSyncUp : 1;
825
826 uint32_t bIsNewFrame : 1;
827 uint32_t bIgnoreCanvasColour : 1;
828 uint32_t bIgnoreLowLevelFlush : 1;
829 uint32_t bHideNavigationLayer : 1;
830 uint32_t bIsDryRun : 1; //!< A flag to indicate whether the first iteration was a dry run
831 uint32_t bNoAdditionalDirtyRegionList : 1;
832 uint32_t bFirstIteration : 1;
833 uint32_t bIsRegionChanged : 1;
834
835 uint32_t bPFBScanPolicyVerticalFirst : 1;
836 uint32_t : 7;
837
838 uint32_t : 8;
839 };
840
841 arm_2d_colour_t tCanvas;
842
843 uintptr_t pFPBPoolAvailable;
844 arm_2d_pfb_t *ptCurrent;
845 arm_2d_pfb_t *ptFreeList;
846 arm_2d_pfb_t *ptFlushing;
847 struct {
848 arm_2d_pfb_t *ptHead;
849 arm_2d_pfb_t *ptTail;
850 }FlushFIFO;
851 arm_2d_tile_t *ptFrameBuffer;
852 } Adapter;
854
855 struct {
856 int64_t lTimestamp; //!< PLEASE DO NOT USE
857 int32_t nTotalCycle; //!< cycles used by drawing
858 int32_t nRenderingCycle; //!< cycles used in LCD flushing
859 } Statistics; //!< performance statistics
860
861};
862
865
867
868ARM_PRIVATE(
871
872 union {
873 arm_2d_region_t tRegions[2];
874 struct {
875 arm_2d_region_t tNewRegion;
876 union {
877 arm_2d_region_t tOldRegion;
878 arm_2d_region_t tEnclosureArea;
879 };
880 };
881 };
882
883 arm_2d_region_t tExtraAreaToInclude;
884
885 uint8_t bForceToUseMinimalEnclosure : 1;
886 uint8_t bSuspendUpdate : 1;
887 uint8_t bIgnore : 1;
888 uint8_t bOnlyUpdateMinimalEnclosure : 1;
889 uint8_t : 4;
890 uint8_t chUpdateLifeCycle; /* a life cycle counter used to avoid repeated update operations in the same frame.*/
891
892 uint16_t u16Key;
894 arm_2d_region_t tRegionPatch;
895
896
897};
898
900
901ARM_PRIVATE(
902 arm_2d_region_list_item_t tDirtyRegion;
903 arm_2d_region_list_item_t **ppDirtyRegionList;
904
905 /* region items */
907
908 uint8_t chUpdateLifeCycle;
909 uint8_t : 8;
910 uint16_t : 16;
912
914
915} ;
916
917/*!
918 * \brief the Transform helper control block
919 *
920 */
922
923 float fAngle;
924 union {
925 float fScale;
926 float fScaleX;
927 };
928 float fScaleY;
929
931ARM_PRIVATE(
932
933 arm_2d_op_t *ptTransformOP;
934
936
937 struct {
938 float fValue;
939 float fStep;
940 } Angle;
941
942 struct {
943 float fValue;
944 float fStep;
945 } ScaleX;
946
947 struct {
948 float fValue;
949 float fStep;
950 } ScaleY;
951
952 bool bNeedUpdate;
954
956
957
958/*!
959 * \brief the Transform helper control block
960 * \note Deprecated.
961 */
962typedef struct {
964
965 float fAngle;
966 float fScale;
967
968ARM_PRIVATE(
969
970 arm_2d_op_t *ptTransformOP;
971
972 struct {
973 float fValue;
974 float fStep;
975 } Angle;
976
977 struct {
978 float fValue;
979 float fStep;
980 } Scale;
981
982 bool bNeedUpdate;
984
986
987
988
989/*============================ GLOBAL VARIABLES ==============================*/
990/*============================ LOCAL VARIABLES ===============================*/
991/*============================ PROTOTYPES ====================================*/
992
993/*!
994 * \brief initialize pfb helper service
995 * \param[in] ptThis the pfb helper control block
996 * \param[in] ptCFG the configuration
997 * \return arm_2d_err_t the process result
998 */
999extern
1000ARM_NONNULL(1,2)
1003/*!
1004 * \brief uninitialize pfb helper service
1005 * \param[in] ptThis the pfb helper control block
1006 * \return none
1007 */
1008extern
1009ARM_NONNULL(1)
1011
1012/*!
1013 * \brief set PFB working policy
1014 * \param[in] ptThis the pfb helper control block
1015 * \param[in] chPolicyMask new policies defined in arm_2d_pfb_scan_policy_t
1016 */
1017extern
1018ARM_NONNULL(1)
1019void arm_2d_helper_pfb_policy(arm_2d_helper_pfb_t *ptThis, uint8_t chPolicyMask);
1020
1021/*!
1022 * \brief get the display (screen) region
1023 * \param[in] ptThis the pfb helper control block
1024 * \return arm_2d_region_t the screen region
1025 */
1026extern
1027ARM_NONNULL(1)
1029
1030/*!
1031 * \brief get the absolute location for a given location on the target tile canvas
1032 * \param[in] ptTile the target tile
1033 * \param[in] tLocation the location on the target tile canvas
1034 * \return arm_2d_location_t the absolute location on a (virtual) screen or on
1035 * a root tile canvas
1036 */
1037extern
1038ARM_NONNULL(1)
1040 arm_2d_tile_t *ptTile,
1041 arm_2d_location_t tLocation);
1042
1043/*!
1044 * \brief get the inital PFB size
1045 * \param[in] ptThis the pfb helper control block
1046 * \return arm_2d_size_t the PFB size
1047 */
1048extern
1049ARM_NONNULL(1)
1051
1052extern
1053/*!
1054 * \brief test whether specified region is being drawing
1055 *
1056 * \param[in] ptTarget the target tile
1057 * \param[in] ptRegion the target region to test
1058 * \param[out] ppVirtualScreen the address of the pointer that used to point
1059 * the virtual screen tile
1060 * \return true the specified region is currently being drawing
1061 * \return false the PFB is out of the range.
1062 */
1064 const arm_2d_region_t *ptRegion,
1065 const arm_2d_tile_t **ppVirtualScreen);
1066
1067extern
1068ARM_NONNULL(2)
1069/*!
1070 * \brief test whether the target region is active (used by PFB service)
1071 *
1072 * \param[in] ptTarget the target tile
1073 * \param[in] ptRegion the target region to test
1074 * \param[in] bConsiderDryRun whether taking dry run into consideration
1075 * \return true the region is active
1076 * \return false the region is inactive
1077 */
1079 const arm_2d_region_t *ptRegion,
1080 bool bConsiderDryRun);
1081
1082extern
1083ARM_NONNULL(2,4)
1084/*!
1085 * \brief test whether the target region is active (used by PFB service)
1086 *
1087 * \param[in] ptTarget the target tile
1088 * \param[in] ptRegion the target region to test
1089 * \param[in] bConsiderDryRun whether taking dry run into consideration
1090 * \param[in] pptScreen a 2rd level pointer to get the virtual screen
1091 * \return true the region is active
1092 * \return false the region is inactive
1093 */
1095 const arm_2d_region_t *ptRegion,
1096 bool bConsiderDryRun,
1097 const arm_2d_tile_t **pptScreen);
1098/*!
1099 * \brief the task function for pfb helper
1100 * \param[in] ptThis an initialised PFB helper control block
1101 * \param[in] ptDirtyRegions a region list pending for refresh, NULL means
1102 * refreshing the whole screen
1103 * \retval arm_fsm_rt_cpl complete refreshing one frame
1104 * \retval arm_fsm_rt_on_going the refreshing work is on-going
1105 * \retval arm_fsm_rt_wait_for_obj user's OnDrawing event handler wants to wait
1106 * for some objects, e.g. semaphore etc.
1107 * \retval <0 An error is detected
1108 */
1109extern
1110ARM_NONNULL(1)
1112 arm_2d_region_list_item_t *ptDirtyRegions);
1113
1114/*!
1115 * \brief flush the FPB FIFO
1116 * \note This function is THREAD-SAFE
1117 * \note For normal usage, please DO NOT use this function unless you know what
1118 * you are doing.
1119 * \param[in] ptThis an initialised PFB helper control block
1120 */
1121extern
1122ARM_NONNULL(1)
1124
1125/*!
1126 * \brief hide the navigation layer
1127 * \param[in] ptThis an initialised PFB helper control block
1128 */
1129extern
1130ARM_NONNULL(1)
1132
1133/*!
1134 * \brief show the navigation layer if there is a valid one
1135 * \param[in] ptThis an initialised PFB helper control block
1136 */
1137extern
1138ARM_NONNULL(1)
1140
1141
1142/*!
1143 * \brief enable filling canvas with specified colour
1144 *
1145 * \param[in] ptThis an initialised PFB helper control block
1146 * \param[in] tColour the target canvas colour
1147 */
1148extern
1149ARM_NONNULL(1)
1151 arm_2d_colour_t tColour);
1152
1153extern
1154ARM_NONNULL(1)
1155/*!
1156 * \brief disable filling canvas with specified colour
1157 *
1158 * \param[in] ptThis an initialised PFB helper control block
1159 */
1161
1162/*!
1163 * \brief ignore the low level PFB flushing only
1164 * \param[in] ptThis an initialised PFB helper control block
1165 */
1166extern
1167ARM_NONNULL(1)
1169
1170/*!
1171 * \brief resume the low level PFB flushing
1172 * \param[in] ptThis an initialised PFB helper control block
1173 */
1174extern
1175ARM_NONNULL(1)
1177
1178/*!
1179 * \brief update PFB dependency (event handlers)
1180 * \param[in] ptThis the PFB helper control block
1181 * \param[in] chMask the bit mask for event handlers
1182 * \param[in] ptDependency the new dependency description
1183 * \return arm_2d_err_t the process result
1184 */
1185extern
1186ARM_NONNULL(1,3)
1188 arm_2d_helper_pfb_t *ptThis,
1189 uint_fast8_t chMask,
1190 const arm_2d_helper_pfb_dependency_t *ptDependency);
1191
1192/*!
1193 * \brief tell PFB helper that a low level LCD flushing work is complete
1194 * \note This function is THREAD-SAFE, You can call this function asynchronously,
1195 * e.g.
1196 * - A ISR to indicate DMA-transfer complete event or
1197 * - A different Thread
1198 * \param[in] ptThis the PFB helper control block
1199 * \param[in] ptPFB the used PFB block
1200 */
1201extern
1202ARM_NONNULL(1)
1204 arm_2d_pfb_t *ptPFB);
1205
1206/*!
1207 * \brief try to get a PFB block from the pool
1208 * \param[in] ptThis the PFB helper control block
1209 * \retval NULL the pool is empty
1210 * \retval !NULL a valid pfb block
1211 */
1212extern
1213ARM_NONNULL(1)
1215
1216/*!
1217 * \brief free a PFB block to the pool
1218 * \param[in] ptThis the PFB helper control block
1219 * \param[in] ptPFB the target PFB block
1220 */
1221extern
1222ARM_NONNULL(1)
1224
1225/*!
1226 * \brief initialize the 3FB (direct mode) service
1227 * \param[in] ptThis the helper service control block
1228 * \param[in] ptCFG the configuration structure
1229 */
1230extern
1231ARM_NONNULL(1,2)
1233 const arm_2d_helper_3fb_cfg_t *ptCFG);
1234
1235
1236/*!
1237 * \brief report the copy-completion event to the 3FB (direct mode) service
1238 * \note see function __arm_2d_helper_3fb_dma_copy for details
1239 * \param[in] ptThis the helper service control block
1240 */
1241extern
1242ARM_NONNULL(1)
1244
1245/*!
1246 * \brief get a pointer for flushing
1247 * \param[in] ptThis the helper service control block
1248 * \return void * the address of a framebuffer
1249 *
1250 * \note please only call this function when on vsync event.
1251 */
1252extern
1253ARM_NONNULL(1)
1255
1256/*!
1257 * \brief please do NOT use this function. It is used by the display adapter.
1258 */
1259extern
1260ARM_NONNULL(1,2)
1262 const arm_2d_pfb_t *ptPFB);
1263
1264
1265/*!
1266 * \brief rotate a given c8bit PFB for 90 degree
1267 * \param[in] ptOrigin the original PFB
1268 * \param[in] ptScratch A scratch PFB
1269 * \param[in] ptScreenSize the screen size
1270 * \return arm_2d_pfb_t * the output PFB
1271 */
1272ARM_NONNULL(1,2,3)
1274 arm_2d_pfb_t *ptOrigin,
1275 arm_2d_pfb_t *ptScratch,
1276 const arm_2d_size_t *ptScreenSize);
1277/*!
1278 * \brief rotate a given c8bit PFB for 180 degree
1279 * \param[in] ptOrigin the original PFB
1280 * \param[in] ptScratch A scratch PFB
1281 * \param[in] ptScreenSize the screen size
1282 * \return arm_2d_pfb_t * the output PFB
1283 */
1284ARM_NONNULL(1,2,3)
1286 arm_2d_pfb_t *ptOrigin,
1287 arm_2d_pfb_t *ptScratch,
1288 const arm_2d_size_t *ptScreenSize);
1289/*!
1290 * \brief rotate a given c8bit PFB for 270 degree
1291 * \param[in] ptOrigin the original PFB
1292 * \param[in] ptScratch A scratch PFB
1293 * \param[in] ptScreenSize the screen size
1294 * \return arm_2d_pfb_t * the output PFB
1295 */
1296ARM_NONNULL(1,2,3)
1298 arm_2d_pfb_t *ptOrigin,
1299 arm_2d_pfb_t *ptScratch,
1300 const arm_2d_size_t *ptScreenSize);
1301
1302/*!
1303 * \brief rotate a given rgb16 PFB for 90 degree
1304 * \param[in] ptOrigin the original PFB
1305 * \param[in] ptScratch A scratch PFB
1306 * \param[in] ptScreenSize the screen size
1307 * \return arm_2d_pfb_t * the output PFB
1308 */
1309ARM_NONNULL(1,2,3)
1311 arm_2d_pfb_t *ptOrigin,
1312 arm_2d_pfb_t *ptScratch,
1313 const arm_2d_size_t *ptScreenSize);
1314
1315/*!
1316 * \brief rotate a given rgb16 PFB for 180 degree
1317 * \param[in] ptOrigin the original PFB
1318 * \param[in] ptScratch A scratch PFB
1319 * \param[in] ptScreenSize the screen size
1320 * \return arm_2d_pfb_t * the output PFB
1321 */
1322ARM_NONNULL(1,2,3)
1324 arm_2d_pfb_t *ptOrigin,
1325 arm_2d_pfb_t *ptScratch,
1326 const arm_2d_size_t *ptScreenSize);
1327
1328/*!
1329 * \brief rotate a given rgb16 PFB for 270 degree
1330 * \param[in] ptOrigin the original PFB
1331 * \param[in] ptScratch A scratch PFB
1332 * \param[in] ptScreenSize the screen size
1333 * \return arm_2d_pfb_t * the output PFB
1334 */
1335ARM_NONNULL(1,2,3)
1337 arm_2d_pfb_t *ptOrigin,
1338 arm_2d_pfb_t *ptScratch,
1339 const arm_2d_size_t *ptScreenSize);
1340
1341/*!
1342 * \brief rotate a given rgb32 PFB for 90 degree
1343 * \param[in] ptOrigin the original PFB
1344 * \param[in] ptScratch A scratch PFB
1345 * \param[in] ptScreenSize the screen size
1346 * \return arm_2d_pfb_t * the output PFB
1347 */
1348ARM_NONNULL(1,2,3)
1350 arm_2d_pfb_t *ptOrigin,
1351 arm_2d_pfb_t *ptScratch,
1352 const arm_2d_size_t *ptScreenSize);
1353/*!
1354 * \brief rotate a given rgb32 PFB for 180 degree
1355 * \param[in] ptOrigin the original PFB
1356 * \param[in] ptScratch A scratch PFB
1357 * \param[in] ptScreenSize the screen size
1358 * \return arm_2d_pfb_t * the output PFB
1359 */
1360ARM_NONNULL(1,2,3)
1362 arm_2d_pfb_t *ptOrigin,
1363 arm_2d_pfb_t *ptScratch,
1364 const arm_2d_size_t *ptScreenSize);
1365
1366/*!
1367 * \brief rotate a given rgb32 PFB for 270 degree
1368 * \param[in] ptOrigin the original PFB
1369 * \param[in] ptScratch A scratch PFB
1370 * \param[in] ptScreenSize the screen size
1371 * \return arm_2d_pfb_t * the output PFB
1372 */
1373ARM_NONNULL(1,2,3)
1375 arm_2d_pfb_t *ptOrigin,
1376 arm_2d_pfb_t *ptScratch,
1377 const arm_2d_size_t *ptScreenSize);
1378
1379/*----------------------------------------------------------------------------*
1380 * Dirty Regions *
1381 *----------------------------------------------------------------------------*/
1382
1383/*!
1384 * \brief append dirty regions to the a specified list
1385 * \param[in] ppDirtyRegionList the target list
1386 * \param[in] ptItems the dirty regions
1387 * \param[in] tCount the number of dirty regions
1388 * \retval true operation is successful
1389 * \retval false the operation is failed.
1390 */
1391extern
1392ARM_NONNULL(1,2)
1394 arm_2d_region_list_item_t **ppDirtyRegionList,
1396 size_t tCount);
1397
1398/*!
1399 * \brief remove dirty regions from the a specified list
1400 * \param[in] ppDirtyRegionList the target list
1401 * \param[in] ptItems the dirty regions
1402 * \param[in] tCount the number of dirty regions
1403 * \retval true operation is successful
1404 * \retval false the operation is failed.
1405 */
1406extern
1407ARM_NONNULL(1,2)
1409 arm_2d_region_list_item_t **ppDirtyRegionList,
1411 size_t tCount);
1412
1413/*!
1414 * \brief decide whether ignore the specified dirty region item
1415 *
1416 * \param[in] ptThis the target dirty region item object
1417 * \param[in] bIgnore whether ignore
1418 * \return bool the previous ignore status
1419 */
1420extern
1421ARM_NONNULL(1)
1423
1424
1425/*!
1426 * \brief get the ignore status of a given dirty region item
1427 *
1428 * \param[in] ptThis the target dirty region item object
1429 * \retval true the dirty region item is ignored.
1430 * \retval false the dirty region item is in-use.
1431 */
1432extern
1433ARM_NONNULL(1)
1435
1436/*!
1437 * \brief enable dirty region optimization service
1438 * \param[in] ptThis the PFB helper control block
1439 * \param[in] ptRegions an optional array of dirty region items, which will be
1440 * added to the dirty region item pool. NULL is acceptable.
1441 * \param[in] chCount the number of items in the array.
1442 */
1443extern
1444ARM_NONNULL(1)
1446 arm_2d_helper_pfb_t *ptThis,
1447 arm_2d_region_list_item_t *ptRegions,
1448 uint_fast8_t chCount);
1449/*!
1450 * \brief disable dirty region optimization service
1451 * \param[in] ptThis the PFB helper control block
1452 * \return previous status
1453 */
1454extern
1455ARM_NONNULL(1)
1457 arm_2d_helper_pfb_t *ptThis);
1458
1459/*----------------------------------------------------------------------------*
1460 * The Dynamic Dirty Region Service *
1461 *----------------------------------------------------------------------------*/
1462/*!
1463 * \brief the on-frame-start event handler for a given user dynamic dirty region
1464 *
1465 * \param[in] ptThis the target region list item.
1466 * \param[in] chUserRegionIndex a specified user region index. When 0xFF is given,
1467 * the existing user region index will not be changed.
1468 *
1469 */
1470extern
1471ARM_NONNULL(1)
1474 uint8_t chUserRegionIndex);
1475
1476/*!
1477 * \brief initialize a dynamic dirty region
1478 *
1479 * \param[in] ptThis the target region list item. If it is NULL, this function will
1480 * allocate an object from the heap
1481 * \return arm_2d_region_list_item_t* the target region list item
1482 */
1483extern
1486
1487/*!
1488 * \brief depose a given dynamic dirty region
1489 *
1490 * \param[in] ptThis the target region list item.
1491 */
1492extern
1493ARM_NONNULL(1)
1495
1496/*!
1497 * \brief wait for the PFB helper service requesting the next region
1498 *
1499 * \param[in] ptThis the target region list item.
1500 * \return uint_fast8_t the user region index
1501 *
1502 * \note You can use the return value, i.e. the user region index to address
1503 * the new region you want to cover.
1504 */
1505extern
1506ARM_NONNULL(1)
1509
1510/*!
1511 * \brief update a given user dynamic dirty region with a new region
1512 *
1513 * \param[in] ptThis the target region list item.
1514 * \param[in] ptTarget the target tile (the frame-buffer to draw)
1515 * \param[in] ptRegion the new region
1516 * \note - when the ptTarget isn't NULL, the ptRegion should points a region inside
1517 * the canvas of the ptTarget (i.e. an relative region of the ptTarget)
1518 * - when the ptTarget is NULL, this function will get the default framebuffer
1519 * by calling the function arm_2d_get_default_frame_buffer().
1520 *
1521 * \param[in] chNextUserIndex the next user region index, 0xFF means complete.
1522 */
1523extern
1524ARM_NONNULL(1)
1526 arm_2d_tile_t *ptTarget,
1527 arm_2d_region_t *ptRegion,
1528 uint8_t chNextUserIndex);
1529
1530/*!
1531 * \brief only change the user region index without update the dynamic dirty region
1532 *
1533 * \param[in] ptThis the target region list item.
1534 * \param[in] chNextUserIndex the next user region index. When encounter 0xFF, the
1535 * user region index will be reset to zero.
1536 */
1537extern
1538ARM_NONNULL(1)
1541 uint8_t chNextUserIndex);
1542
1543/*----------------------------------------------------------------------------*
1544 * The Dirty Region Helper Service *
1545 *----------------------------------------------------------------------------*/
1546
1547/*!
1548 * \brief initialize a given dirtt region helper
1549 * \param[in] ptThis the target helper
1550 * \param[in] ppDirtyRegionList the address of the dirty region list
1551 */
1552extern
1553ARM_NONNULL(1,2)
1556 arm_2d_region_list_item_t **ppDirtyRegionList);
1557extern
1558ARM_NONNULL(1,2)
1559/*!
1560 * \brief add an array of region items to a dirty region helper
1561 *
1562 * \param[in] ptThis the target helper
1563 * \param[in] ptItems the array of the region items
1564 * \param[in] hwCount the number of items in the array
1565 */
1569 uint_fast16_t hwCount);
1570extern
1571ARM_NONNULL(1,2)
1572/*!
1573 * \brief remove an array of region items to a dirty region helper
1574 *
1575 * \param[in] ptThis the target helper
1576 * \param[in] ptItems the array of the region items
1577 * \param[in] hwCount the number of items in the array
1578 */
1582 uint_fast16_t hwCount);
1583
1584/*!
1585 * \brief depose a given dirty region helper
1586 * \param[in] ptThis the target helper
1587 * \return arm_2d_helper_dirty_region_item_t * the region list items
1588 */
1589extern
1590ARM_NONNULL(1)
1592
1593/*!
1594 * \brief the on-frame-start event handler for a given dirty region helper
1595 * \param[in] ptThis the target helper
1596 * \note Usually this event handler should be insert the frame start event
1597 * handler of a target scene.
1598 */
1599extern
1600ARM_NONNULL(1)
1603
1604/*!
1605 * \brief update a specified new region while erase the previous region
1606 *
1607 * \param[in] ptThis the target region item
1608 * \param[in] ptTargetTile the target tile to draw content
1609 * \param[in] ptVisibleArea a visible region in the target tile used to clip
1610 * the ptNewRegion, NULL means no clipping.
1611 * \param[in] ptNewRegion the new region to update, NULL means nothing
1612 * to update
1613 */
1614extern
1615ARM_NONNULL(1,2)
1618 const arm_2d_tile_t *ptTargetTile,
1619 const arm_2d_region_t *ptVisibleArea,
1620 const arm_2d_region_t *ptNewRegion);
1621
1622/*!
1623 * \brief update the "extra area" of a specified dirty region item
1624 *
1625 * \param[in] ptThis the target region item
1626 * \param[in] ptTargetTile the target tile to draw content
1627 * \param[in] ptVisibleArea a visible region in the target tile used to clip
1628 * the ptNewRegion, NULL means no clipping.
1629 * \param[in] ptExtraRegion the new extra region
1630 */
1631extern
1632ARM_NONNULL(1,2)
1635 const arm_2d_tile_t *ptTargetTile,
1636 const arm_2d_region_t *ptVisibleArea,
1637 const arm_2d_region_t *ptExtraRegion);
1638
1639/*!
1640 * \brief update a specified new region while erase the previous region
1641 *
1642 * \param[in] ptThis the target helper
1643 * \param[in] ptTargetTile the target tile to draw content
1644 */
1645ARM_NONNULL(1,2)
1646extern
1649 const arm_2d_tile_t *ptTargetTile);
1650
1651/*!
1652 * \brief update a specified new region while erase the previous region
1653 *
1654 * \param[in] ptThis the target helper
1655 * \param[in] ptTargetTile the target tile to draw content
1656 * \param[in] ptVisibleArea a visible region in the target tile used to clip
1657 * the ptNewRegion, NULL means no clipping.
1658 * \param[in] ptNewRegion the new region to update, NULL means nothing
1659 * to update
1660 */
1661extern
1662ARM_NONNULL(1,2)
1665 const arm_2d_tile_t *ptTargetTile,
1666 const arm_2d_region_t *ptVisibleArea,
1667 const arm_2d_region_t *ptNewRegion);
1668
1669/*!
1670 * \brief force an arm_2d_helper_dirty_region_item_t object to use the minimal
1671 * enclosure region to update.
1672 *
1673 * \param[in] ptThis the target item
1674 * \param[in] bEnable whether enable this feature.
1675 * \return boolean the original setting
1676 */
1677ARM_NONNULL(1)
1680 bool bEnable);
1681
1682/*!
1683 * \brief force the dirty region helper to use the minimal enclosure region to
1684 * update.
1685 *
1686 * \param[in] ptThis the target helper
1687 * \param[in] bEnable whether enable this feature.
1688 * \return boolean the original setting
1689 */
1690extern
1691ARM_NONNULL(1)
1694 bool bEnable);
1695
1696/*!
1697 * \brief force the dirty region helper to suspend the dirty region update.
1698 *
1699 * \param[in] ptThis the target helper
1700 * \param[in] bEnable whether enable this feature.
1701 * \return boolean the original setting
1702 */
1703extern
1704ARM_NONNULL(1)
1707 bool bEnable);
1708
1709/*!
1710 * \brief force the arm_2d_helper_dirty_region_item_t object to suspend the
1711 * dirty region update.
1712 *
1713 * \param[in] ptThis the target item
1714 * \param[in] bEnable whether enable this feature.
1715 * \return boolean the original setting
1716 */
1717ARM_NONNULL(1)
1720 bool bEnable);
1721
1722/*----------------------------------------------------------------------------*
1723 * The Transform Helper Service (Deprecated) *
1724 *----------------------------------------------------------------------------*/
1725/*!
1726 * \brief initialize a given transform helper
1727 * \note Deprecated.
1728 * \param[in] ptThis the target helper
1729 * \param[in] ptTransformOP the target transform OP, NULL is not accepted.
1730 * \param[in] fAngleStep the minimal acceptable angle change.
1731 * \param[in] fScaleStep the minimal acceptable scale ratio change.
1732 * \param[in] ppDirtyRegionList the address of the dirty region list
1733 */
1734extern
1735ARM_NONNULL(1,2,5)
1737 arm_2d_op_t *ptTransformOP,
1738 float fAngleStep,
1739 float fScaleStep,
1740 arm_2d_region_list_item_t **ppDirtyRegionList);
1741
1742/*!
1743 * \brief depose a given transform helper
1744 * \note Deprecated.
1745 * \param[in] ptThis the target helper
1746 */
1747extern
1748ARM_NONNULL(1)
1750
1751/*!
1752 * \brief the on-frame-begin event handler for a given transform helper
1753 * \note Deprecated.
1754 * \param[in] ptThis the target helper
1755 * \note Usually this event handler should be insert the frame start event
1756 * handler of a target scene.
1757 */
1758extern
1759ARM_NONNULL(1)
1761
1762/*!
1763 * \brief force transform helper to update dirty region
1764 * \note Deprecated.
1765 * \note sometimes, we want to force transform helper to update dirty regions
1766 * even if both the angel and scale keep the same, for example, the pivots
1767 * are updated.
1768 * \param[in] ptThis the target helper
1769 */
1770extern
1771ARM_NONNULL(1)
1773
1774/*!
1775 * \brief force the transform helper to use the minimal enclosure region as
1776 * the dirty region.
1777 * \note Deprecated.
1778 * \param[in] ptThis the target helper
1779 * \param[in] bEnable whether enable this feature.
1780 * \return boolean the original setting
1781 */
1782extern
1783ARM_NONNULL(1)
1786 bool bEnable);
1787
1788/*!
1789 * \brief force the transform helper to suspend the dirty region update.
1790 * \note Deprecated.
1791 * \param[in] ptThis the target helper
1792 * \param[in] bEnable whether enable this feature.
1793 * \return boolean the original setting
1794 */
1795extern
1796ARM_NONNULL(1)
1798 bool bEnable);
1799
1800/*!
1801 * \brief update a given transform helper with new values
1802 * \note Deprecated.
1803 * \param[in] ptThis the target helper
1804 * \param[in] fAngle the new angle value
1805 * \param[in] fScale the new scale ratio
1806 * \note The new value is only accepted when the change between the old value
1807 * and the new value is larger than the minimal acceptable mount.
1808 */
1809extern
1810ARM_NONNULL(1)
1812 float fAngle,
1813 float fScale);
1814
1815/*!
1816 * \brief update the dirty region after a transform operation
1817 * \note Deprecated.
1818 * \param[in] ptThis the target helper
1819 * \param[in] ptCanvas the canvas
1820 * \param[in] bIsNewFrame whether this is a new frame
1821 */
1822extern
1823ARM_NONNULL(1)
1826 const arm_2d_region_t *ptCanvas,
1827 bool bIsNewFrame);
1828
1829
1830/*----------------------------------------------------------------------------*
1831 * The Dirty Region Transform Helper Service *
1832 *----------------------------------------------------------------------------*/
1833/*!
1834 * \brief initialize a given dirty region transform helper
1835 *
1836 * \param[in] ptThis the target helper
1837 * \param[in] ptHelper the host arm_2d_helper_dirty_region_t object.
1838 * \param[in] ptTransformOP the target transform OP, NULL is not accepted.
1839 * \param[in] fAngleStep the minimal acceptable angle change.
1840 * \param[in] fScaleStep the minimal acceptable scale ratio change.
1841 */
1842extern
1843ARM_NONNULL(1,2,3)
1847 arm_2d_op_t *ptTransformOP,
1848 float fAngleStep,
1849 float fScaleStep);
1850
1851/*!
1852 * \brief depose a given dirty region transform helper
1853 *
1854 * \param[in] ptThis the target helper
1855 */
1856extern
1857ARM_NONNULL(1)
1860
1861/*!
1862 * \brief the on-frame-begin event handler for a given dirty region transform
1863 * helper
1864 *
1865 * \param[in] ptThis the target helper
1866 * \note Usually this event handler should be insert the frame start event
1867 * handler of a target scene.
1868 */
1869extern
1870ARM_NONNULL(1)
1873
1874/*!
1875 * \brief force a dirty region transform helper to update its dirty region
1876 *
1877 * \note sometimes, we want to force transform helper to update dirty regions
1878 * even if both the angel and scale keep the same, for example, the pivots
1879 * are updated.
1880 * \param[in] ptThis the target helper
1881 */
1882extern
1883ARM_NONNULL(1)
1886
1887/*!
1888 * \brief force a dirty region transform helper to use the minimal enclosure
1889 * region as the dirty region.
1890 *
1891 * \param[in] ptThis the target helper
1892 * \param[in] bEnable whether enable this feature.
1893 * \return boolean the original setting
1894 */
1895extern
1896ARM_NONNULL(1)
1899 bool bEnable);
1900
1901/*!
1902 * \brief force a dirty region transform helper to suspend updating.
1903 *
1904 * \param[in] ptThis the target helper
1905 * \param[in] bEnable whether enable this feature.
1906 * \return boolean the original setting
1907 */
1908extern
1909ARM_NONNULL(1)
1912 bool bEnable);
1913
1914/*!
1915 * \brief update a given dirty region transform helper with new values
1916 *
1917 * \param[in] ptThis the target helper
1918 * \param[in] fAngle the new angle value
1919 * \param[in] fScale the new scale ratio
1920 * \note The new value is only accepted when the change between the old value
1921 * and the new value is larger than the minimal acceptable mount.
1922 */
1923extern
1924ARM_NONNULL(1)
1927 float fAngle,
1928 float fScale);
1929
1930/*!
1931 * \brief update a given dirty region transform helper with new values
1932 *
1933 * \param[in] ptThis the target helper
1934 * \param[in] fAngle the new angle value
1935 * \param[in] fScaleX the new scale ratio for X axis
1936 * \param[in] fScaleY the new scale ratio for Y axis
1937 * \note The new value is only accepted when the change between the old value
1938 * and the new value is larger than the minimal acceptable mount.
1939 */
1940extern
1941ARM_NONNULL(1)
1944 float fAngle,
1945 float fScaleX,
1946 float fScaleY);
1947
1948/*!
1949 * \brief update the dirty region after a transform operation
1950 *
1951 * \param[in] ptThis the target helper
1952 * \param[in] ptCanvas the canvas
1953 * \param[in] bIsNewFrame whether this is a new frame
1954 */
1955extern
1956ARM_NONNULL(1)
1959 const arm_2d_region_t *ptCanvas,
1960 bool bIsNewFrame);
1961
1962
1963/*! @} */
1964
1965#if defined(__clang__)
1966# pragma clang diagnostic pop
1967#endif
1968
1969#ifdef __cplusplus
1970}
1971#endif
1972
1973
1974
1975#endif