diff --git a/docs/integration/chip/stm32.rst b/docs/integration/chip/stm32.rst index 2e9c5fbeb..4e7ce7fa5 100644 --- a/docs/integration/chip/stm32.rst +++ b/docs/integration/chip/stm32.rst @@ -270,6 +270,8 @@ A minimal example using STM32CubeIDE, HAL, and CMSISv1 (FreeRTOS). lv_display_flush_ready(display); } +.. _dma2d: + DMA2D Support ------------- @@ -289,3 +291,5 @@ instead of "busywait" while waiting for a DMA2D transfer to complete. If ``LV_USE_DRAW_DMA2D_INTERRUPT`` is enabled then you are required to call :cpp:expr:`lv_draw_dma2d_transfer_complete_interrupt_handler` whenever the DMA2D "transfer complete" global interrupt is received. + +If your STM device has a Nema GPU, you can use the :ref:`Nema GFX renderer ` instead. diff --git a/docs/overview/renderers/index.rst b/docs/overview/renderers/index.rst index 7232e4e95..a68dedf90 100644 --- a/docs/overview/renderers/index.rst +++ b/docs/overview/renderers/index.rst @@ -12,3 +12,4 @@ Renderers and GPUs stm32_dma2d vglite vg_lite + nema_gfx diff --git a/docs/overview/renderers/nema_gfx.rst b/docs/overview/renderers/nema_gfx.rst new file mode 100644 index 000000000..913c3cac3 --- /dev/null +++ b/docs/overview/renderers/nema_gfx.rst @@ -0,0 +1,73 @@ +.. _stm32_nema_gfx: + +=================================== +NemaGFX Acceleration (AKA NeoChrom) +=================================== + +Some of the more powerful STM32 MCUs such as the +STM32U5 feature a 2.5D GPU which can natively draw most +LVGL primitives. + +Get Started with the Riverdi STM32U5 5-inch Display +*************************************************** + +`lv_port_riverdi_stm32u5 `__ +is a ready-to-use port for the Riverdi STM32 5.0" Embedded Display +(STM32U599NJH6Q or STM32U5A9NJH6Q) which has Nema enabled. +Follow the instructions in the readme to get started. + +Usage and Configuration +*********************** + +Enable the renderer by setting :c:macro:`LV_USE_NEMA_GFX` to ``1`` in +lv_conf.h. If using :c:macro:`LV_USE_NEMA_VG`, +set :c:macro:`LV_NEMA_GFX_MAX_RESX` and :c:macro:`LV_NEMA_GFX_MAX_RESY` +to the size of the display you will be using so that enough static +memory will be reserved for VG. Without VG, more task types will be +performed by the software renderer. + +"libs/nema_gfx" contains pre-compiled binaries for the Nema GPU +drivers. In `lv_port_riverdi_stm32u5 `__ +the project is already configured to link the binaries when building. +With a different STM32CubeIDE project, you can configure the libraries to be linked +by right-clicking the project in the "Project Explorer" sidebar, clicking +"Properties", navigating to "C/C++ Build", "Settings", "MCU G++ Linker", and then +"Libraries". Add an entry under "Libraries (-l)" that is "nemagfx-float-abi-hard". +Add an entry under "Library search path (-L)" which is a path to +"libs/nema_gfx/lib/core/cortex_m33/gcc" e.g. +"${workspace_loc:/${ProjName}/Middlewares/LVGL/lvgl/libs/nema_gfx/lib/core/cortex_m33/gcc}". +You will also want to add the "libs/nema_gfx/include" directory to your include +search paths. Under "MCU GCC Compiler", "Include paths", add an entry to "Include paths (-I)" +which is a path to "libs/nema_gfx/include" e.g. +"${workspace_loc:/${ProjName}/Middlewares/LVGL/lvgl/libs/nema_gfx/include}". +Click "Apply and Close". + +32 and 16 bit :c:macro:`LV_COLOR_DEPTH` is supported. + +At the time of writing, :c:macro:`LV_USE_OS` support is experimental +and not yet working in +`lv_port_riverdi_stm32u5 `__ + +"src/draw/nema_gfx/lv_draw_nema_gfx_hal.c" implements the HAL functionality +required by Nema to allocate memory and lock resources (in this implementation, +no locking is done). It may conflict with existing definitions +if you have an existing Nema HAL implementation. You may +simply be able to remove yours. + +DMA2D +***** + +The Nema renderer uses DMA2D to flush in parallel with rendering in +`lv_port_riverdi_stm32u5 `__. + +If your STM does not have the Nema GPU, it may still support +DMA2D. DMA2D is a simple peripheral which can draw fills +and images independently of the CPU. +See the LVGL :ref:`DMA2D support `. + +API +*** + +:ref:`lv_draw_nema_gfx_h` + +:ref:`lv_draw_nema_gfx_utils_h` diff --git a/libs/nema_gfx/include/build_version.h b/libs/nema_gfx/include/build_version.h new file mode 100644 index 000000000..401fd6ec6 --- /dev/null +++ b/libs/nema_gfx/include/build_version.h @@ -0,0 +1 @@ +// Build Hash: f02602a9bc58957911babb1a647e6b0019983cb7 diff --git a/libs/nema_gfx/include/nema_blender.h b/libs/nema_gfx/include/nema_blender.h new file mode 100644 index 000000000..49377af9e --- /dev/null +++ b/libs/nema_gfx/include/nema_blender.h @@ -0,0 +1,178 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + + +#ifndef NEMA_BLENDER_H__ +#define NEMA_BLENDER_H__ + +#include "nema_sys_defs.h" +#include "nema_graphics.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Blending Factor Selector +//----------------------------------------------------------------------------------------------------------------------- +#define NEMA_BF_ZERO (0x0U) /**< 0 */ +#define NEMA_BF_ONE (0x1U) /**< 1 */ +#define NEMA_BF_SRCCOLOR (0x2U) /**< Sc */ +#define NEMA_BF_INVSRCCOLOR (0x3U) /**< (1-Sc) */ +#define NEMA_BF_SRCALPHA (0x4U) /**< Sa */ +#define NEMA_BF_INVSRCALPHA (0x5U) /**< (1-Sa) */ +#define NEMA_BF_DESTALPHA (0x6U) /**< Da */ +#define NEMA_BF_INVDESTALPHA (0x7U) /**< (1-Da) */ +#define NEMA_BF_DESTCOLOR (0x8U) /**< Dc */ +#define NEMA_BF_INVDESTCOLOR (0x9U) /**< (1-Dc) */ +#define NEMA_BF_CONSTCOLOR (0xaU) /**< Cc */ +#define NEMA_BF_CONSTALPHA (0xbU) /**< Ca */ + + /* source factor destination factor */ +#define NEMA_BL_SIMPLE ( (uint32_t)NEMA_BF_SRCALPHA | ((uint32_t)NEMA_BF_INVSRCALPHA <<8) ) /**< Sa * Sa + Da * (1 - Sa) */ +#define NEMA_BL_CLEAR ( (uint32_t)NEMA_BF_ZERO /*| ((uint32_t)NEMA_BF_ZERO <<8)*/) /**< 0 */ +#define NEMA_BL_SRC ( (uint32_t)NEMA_BF_ONE /*| ((uint32_t)NEMA_BF_ZERO <<8)*/) /**< Sa */ +#define NEMA_BL_SRC_OVER ( (uint32_t)NEMA_BF_ONE | ((uint32_t)NEMA_BF_INVSRCALPHA <<8) ) /**< Sa + Da * (1 - Sa) */ +#define NEMA_BL_DST_OVER ( (uint32_t)NEMA_BF_INVDESTALPHA | ((uint32_t)NEMA_BF_ONE <<8) ) /**< Sa * (1 - Da) + Da */ +#define NEMA_BL_SRC_IN ( (uint32_t)NEMA_BF_DESTALPHA /*| ((uint32_t)NEMA_BF_ZERO <<8)*/) /**< Sa * Da */ +#define NEMA_BL_DST_IN (/*(uint32_t)NEMA_BF_ZERO |*/ ((uint32_t)NEMA_BF_SRCALPHA <<8) ) /**< Da * Sa */ +#define NEMA_BL_SRC_OUT ( (uint32_t)NEMA_BF_INVDESTALPHA/*| ((uint32_t)NEMA_BF_ZERO <<8)*/ ) /**< Sa * (1 - Da) */ +#define NEMA_BL_DST_OUT (/*(uint32_t)NEMA_BF_ZERO |*/ ((uint32_t)NEMA_BF_INVSRCALPHA <<8) ) /**< Da * (1 - Sa) */ +#define NEMA_BL_SRC_ATOP ( (uint32_t)NEMA_BF_DESTALPHA | ((uint32_t)NEMA_BF_INVSRCALPHA <<8) ) /**< Sa * Da + Da * (1 - Sa) */ +#define NEMA_BL_DST_ATOP ( (uint32_t)NEMA_BF_INVDESTALPHA | ((uint32_t)NEMA_BF_SRCALPHA <<8) ) /**< Sa * (1 - Da) + Da * Sa */ +#define NEMA_BL_ADD ( (uint32_t)NEMA_BF_ONE | ((uint32_t)NEMA_BF_ONE <<8) ) /**< Sa + Da */ +#define NEMA_BL_XOR ( (uint32_t)NEMA_BF_INVDESTALPHA | ((uint32_t)NEMA_BF_INVSRCALPHA <<8) ) /**< Sa * (1 - Da) + Da * (1 - Sa) */ + + +#define NEMA_BLOP_NONE (0U) /**< No extra blending operation */ +#define NEMA_BLOP_LUT (0x00200000U) /**< src_tex as index, src2_tex as palette */ +#define NEMA_BLOP_STENCIL_XY (0x00400000U) /**< Use TEX3 as mask */ +#define NEMA_BLOP_STENCIL_TXTY (0x00800000U) /**< Use TEX3 as mask */ +#define NEMA_BLOP_NO_USE_ROPBL (0x01000000U) /**< Don't use Rop Blender even if present */ +#define NEMA_BLOP_DST_CKEY_NEG (0x02000000U) /**< Apply Inverse Destination Color Keying - draw only when dst color doesn't match colorkey*/ +#define NEMA_BLOP_SRC_PREMULT (0x04000000U) /**< Premultiply Source Color with Source Alpha (cannot be used with NEMA_BLOP_MODULATE_RGB) */ +#define NEMA_BLOP_MODULATE_A (0x08000000U) /**< Modulate by Constant Alpha value*/ +#define NEMA_BLOP_FORCE_A (0x10000000U) /**< Force Constant Alpha value */ +#define NEMA_BLOP_MODULATE_RGB (0x20000000U) /**< Modulate by Constant Color (RGB) values */ +#define NEMA_BLOP_SRC_CKEY (0x40000000U) /**< Apply Source Color Keying - draw only when src color doesn't match colorkey */ +#define NEMA_BLOP_DST_CKEY (0x80000000U) /**< Apply Destination Color Keying - draw only when dst color matches colorkey */ +#define NEMA_BLOP_MASK (0xffe00000U) + +/** \brief Return blending mode given source and destination blending factors and additional blending operations + * + * \param src Source Blending Factor + * \param dst Destination Blending Factor + * \param ops Additional Blending Operations + * \return Final Blending Mode + * + */ +static inline uint32_t nema_blending_mode(uint32_t src_bf, uint32_t dst_bf, uint32_t blops) { + return ( (src_bf) | (dst_bf << 8) | (blops&NEMA_BLOP_MASK) ); +} + +/** \brief Set blending mode + * + * \param blending_mode Blending mode to be set + * \param dst_tex Destination Texture + * \param fg_tex Foreground (source) Texture + * \param bg_tex Background (source2) Texture + * + */ +void nema_set_blend(uint32_t blending_mode, nema_tex_t dst_tex, nema_tex_t fg_tex, nema_tex_t bg_tex); + +/** \brief Set blending mode for filling + * + * \param blending_mode Blending mode to be set + * + */ +static inline void nema_set_blend_fill(uint32_t blending_mode) { + nema_set_blend(blending_mode, NEMA_TEX0, NEMA_NOTEX, NEMA_NOTEX); +} + +/** \brief Set blending mode for filling with composing + * + * \param blending_mode Blending mode to be set + * + */ +static inline void nema_set_blend_fill_compose(uint32_t blending_mode) { + nema_set_blend(blending_mode, NEMA_TEX0, NEMA_NOTEX, NEMA_TEX2); +} + +/** \brief Set blending mode for blitting + * + * \param blending_mode Blending mode to be set + * + */ +static inline void nema_set_blend_blit(uint32_t blending_mode) { + nema_set_blend(blending_mode, NEMA_TEX0, NEMA_TEX1, NEMA_NOTEX); +} + +/** \brief Set blending mode for blitting with composing + * + * \param blending_mode Blending mode to be set + * + */ +static inline void nema_set_blend_blit_compose(uint32_t blending_mode) { + nema_set_blend(blending_mode, NEMA_TEX0, NEMA_TEX1, NEMA_TEX2); +} + +/** \brief Set constant color + * + * \param rgba RGBA color + * \see nema_rgba() + * + */ +void nema_set_const_color(uint32_t rgba); + +/** \brief Set source color key + * + * \param rgba RGBA color key + * \see nema_rgba() + * + */ +void nema_set_src_color_key(uint32_t rgba); + +/** \brief Set destination color key + * + * \param rgba RGBA color key + * \see nema_rgba() + * + */ +void nema_set_dst_color_key(uint32_t rgba); + + +/** \brief Enable/disable ovedraw debugging. Disables gradient and texture, forces blending mode to NEMA_BL_ADD + * + * \param enable Enables overdraw debugging if non-zero + * + */ +void nema_debug_overdraws(uint32_t enable); + +#ifdef __cplusplus +} +#endif + +#endif // NEMA_BLENDER_H__ diff --git a/libs/nema_gfx/include/nema_cmdlist.h b/libs/nema_gfx/include/nema_cmdlist.h new file mode 100644 index 000000000..1f13adef3 --- /dev/null +++ b/libs/nema_gfx/include/nema_cmdlist.h @@ -0,0 +1,208 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + + +#ifndef NEMA_CMDLIST_H__ +#define NEMA_CMDLIST_H__ + +#include "nema_sys_defs.h" +#include "nema_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define CL_NOP 0x010000U +#define CL_PUSH 0x020000U +#define CL_RETURN 0x040000U +#define CL_ABORT 0x080000U + +#define CL_BATCH_SHIFT 12 +#define CL_BATCH_LOOP 0x8000 + +#define SUBMISSION_ID_MASK 0xffffff + +#define CL_ALIGNMENT_MASK (0x00000007U) // CL buffer must be 8 byte aligned + +//--------------------------------------------------------------------------- +typedef struct nema_cmdlist_t_ { + nema_buffer_t bo; + int size; /**< Number of entries in the command list */ + int offset; /**< Points to the next address to write */ + uint32_t flags; /**< Flags */ + int32_t submission_id; + struct nema_cmdlist_t_ *next; /**< Points to next command list */ + struct nema_cmdlist_t_ *root; /**< Points to the head of the list */ +} nema_cmdlist_t; + +/** \brief Create a new Command List into a preallocated space + * + * \param addr_virt Command List's address (preallocated) + * \param size_bytes Command List's size in bytes + * \return The instance of the new Command List + * + */ +nema_cmdlist_t nema_cl_create_prealloc(nema_buffer_t *bo); + +/** \brief Create a new, non expandable Command List of specific size + * + * \param size_bytes Command List's size in bytes + * \return The instance of the new Command List + * + */ +nema_cmdlist_t nema_cl_create_sized(int size_bytes); + +/** \brief Create a new expandable Command List + * + * \return The instance of the new Command List + * + */ +nema_cmdlist_t nema_cl_create(void); + +/** \brief Destroy/Free a Command List + * + * \param cl Pointer to the Command List + * + */ +void nema_cl_destroy(nema_cmdlist_t *cl); + +/** \brief Reset position of next command to be written to the beginning. Doesn't clear the List's contents. + * + * \param cl Pointer to the Command List + * + */ +void nema_cl_rewind(nema_cmdlist_t *cl); + +/** \brief Define in which Command List each subsequent commands are going to be inserted. + * + * \param cl Pointer to the Command List + * + */ +void nema_cl_bind(nema_cmdlist_t *cl); + +/** \brief Define in which Command List each subsequent commands are going to be inserted. + * Bind this command list as Circular. It never gets full, it never expands, + * it may get implicitly submitted, it cannot be reused. No other CL should be submitted + * while a circular CL is bound + * + * \param cl Pointer to the Command List + * + */ +void nema_cl_bind_circular(nema_cmdlist_t *cl); + +/** \brief Unbind current bound Command List, if any. + * + * + */ +void nema_cl_unbind(void); + + +/** \brief Get bound Command List + * + * \return Pointer to the bound Command List + * + */ +nema_cmdlist_t *nema_cl_get_bound(void); + +/** \private */ +void nema_cl_submit_no_irq(nema_cmdlist_t *cl); + +/** \brief Enqueue Command List to the Ring Buffer for execution + * + * \param cl Pointer to the Command List + * + */ +void nema_cl_submit(nema_cmdlist_t *cl); + +/** \brief Wait for Command List to finish + * + * \param cl Pointer to the Command List + * \return 0 if no error has occurred + * + */ +int nema_cl_wait(nema_cmdlist_t *cl); + +/** \brief Add a command to the bound Command List + * + * \param reg Hardware register to be written + * \param data Data to be written + * + */ +void nema_cl_add_cmd(uint32_t reg, uint32_t data); + +/** \brief Add multiple commands to the bound Command List + * + * \param cmd_no Numbers of commands to add + * \param cmd Pointer to the commands to be added + * \return 0 if no error has occurred + * + */ +int nema_cl_add_multiple_cmds(int cmd_no, uint32_t *cmd); + +/** private */ +uint32_t * nema_cl_get_space(int cmd_no); + +/** \brief Branch from the bound Command List to a different one. Return is implied. + * + * \param cl Pointer to the Command List to branch to + * + */ +void nema_cl_branch(nema_cmdlist_t *cl); + +/** \brief Jump from the bound Command List to a different one. No return is implied. + * + * \param cl Pointer to the Command List to jump to + * + */ +void nema_cl_jump(nema_cmdlist_t *cl); + +/** \brief Add an explicit return command to the bound Command List + * + * + */ +void nema_cl_return(void); + +/** \brief Returns positive number if the Command List is almost full, otherwise returns 0. + * + * \param cl Pointer to the Command List + * + */ +int nema_cl_almost_full(nema_cmdlist_t *cl); + +/** \brief Check if there is enough space or expansion can be performed for + * required commands. + * + * \param cmd_no Numbers of commands to be checked if they fit + * \reurn zero is commands fit or expansion xan be performed else return negative + */ +int nema_cl_enough_space(int cmd_no); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libs/nema_gfx/include/nema_core.h b/libs/nema_gfx/include/nema_core.h new file mode 100644 index 000000000..2942e9ece --- /dev/null +++ b/libs/nema_gfx/include/nema_core.h @@ -0,0 +1,41 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + + +#ifndef NEMA_CORE_H__ +#define NEMA_CORE_H__ + +#include "nema_hal.h" +#include "nema_cmdlist.h" +#include "nema_graphics.h" +#include "nema_interpolators.h" +#include "nema_blender.h" +#include "nema_math.h" +#include "nema_matrix3x3.h" +#include "nema_matrix4x4.h" + +#endif diff --git a/libs/nema_gfx/include/nema_easing.h b/libs/nema_gfx/include/nema_easing.h new file mode 100644 index 000000000..936b1c0c2 --- /dev/null +++ b/libs/nema_gfx/include/nema_easing.h @@ -0,0 +1,369 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + + +#ifndef NEMA_EASING_H__ +#define NEMA_EASING_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//Linear + +// Modeled after the line y = x +/** \brief Linear easing, no acceleration + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_linear(float p); + +//Quadratic + +// Modeled after the parabola y = x^2 +/** \brief Quadratic easing in, accelerate from zero + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_quad_in(float p); + +// Modeled after the parabola y = -x^2 + 2x +/** \brief Quadratic easing out, decelerate to zero velocity + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_quad_out(float p); + +// Modeled after the piecewise quadratic +// y = (1/2)((2x)^2) ; [0, 0.5) +// y = -(1/2)((2x-1)*(2x-3) - 1) ; [0.5, 1] +/** \brief Quadratic easing in and out, accelerate to halfway, then decelerate + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_quad_in_out(float p); + +//Cubic + +// Modeled after the cubic y = x^3 +/** \brief Cubic easing in, accelerate from zero + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_cub_in(float p); + +// Modeled after the cubic y = (x - 1)^3 + 1 +/** \brief Cubic easing out, decelerate to zero velocity + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_cub_out(float p); + +// Modeled after the piecewise cubic +// y = (1/2)((2x)^3) ; [0, 0.5) +// y = (1/2)((2x-2)^3 + 2) ; [0.5, 1] +/** \brief Cubic easing in and out, accelerate to halfway, then decelerate + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_cub_in_out(float p); + +//Quartic + +// Modeled after the quartic x^4 +/** \brief Quartic easing in, accelerate from zero + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_quar_in(float p); + +// Modeled after the quartic y = 1 - (x - 1)^4 +/** \brief Quartic easing out, decelerate to zero velocity + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_quar_out(float p); + +// Modeled after the piecewise quartic +// y = (1/2)((2x)^4) ; [0, 0.5) +// y = -(1/2)((2x-2)^4 - 2) ; [0.5, 1] +/** \brief Quartic easing in and out, accelerate to halfway, then decelerate + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_quar_in_out(float p); + +//Quintic + +// Modeled after the quintic y = x^5 +/** \brief Quintic easing in, accelerate from zero + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_quin_in(float p); + +// Modeled after the quintic y = (x - 1)^5 + 1 +/** \brief Quintic easing out, decelerate to zero velocity + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_quin_out(float p); + +// Modeled after the piecewise quintic +// y = (1/2)((2x)^5) ; [0, 0.5) +// y = (1/2)((2x-2)^5 + 2) ; [0.5, 1] +/** \brief Quintic easing in and out, accelerate to halfway, then decelerate + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_quin_in_out(float p); + +//Sin + +// Modeled after quarter-cycle of sine wave +/** \brief Sinusoidal easing in, accelerate from zero + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_sin_in(float p); + +// Modeled after quarter-cycle of sine wave (different phase) +/** \brief Sinusoidal easing out, decelerate to zero velocity + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_sin_out(float p); + +// Modeled after half sine wave +/** \brief Sinusoidal easing in and out, accelerate to halfway, then decelerate + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_sin_in_out(float p); + +//Circular + +// Modeled after shifted quadrant IV of unit circle +/** \brief Circular easing in, accelerate from zero + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_circ_in(float p); + +// Modeled after shifted quadrant II of unit circle +/** \brief Circular easing out, decelerate to zero velocity + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_circ_out(float p); + +// Modeled after the piecewise circular function +// y = (1/2)(1 - sqrt(1 - 4x^2)) ; [0, 0.5) +// y = (1/2)(sqrt(-(2x - 3)*(2x - 1)) + 1) ; [0.5, 1] +/** \brief Circular easing in and out, accelerate to halfway, then decelerate + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_circ_in_out(float p); + +//Exponential + +// Modeled after the exponential function y = 2^(10(x - 1)) +/** \brief Exponential easing in, accelerate from zero + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_exp_in(float p); + +// Modeled after the exponential function y = -2^(-10x) + 1 +/** \brief Exponential easing out, decelerate to zero velocity + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_exp_out(float p); + +// Modeled after the piecewise exponential +// y = (1/2)2^(10(2x - 1)) ; [0,0.5) +// y = -(1/2)*2^(-10(2x - 1))) + 1 ; [0.5,1] +/** \brief Exponential easing in and out, accelerate to halfway, then decelerate + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_exp_in_out(float p); + +//Elastic +// Modeled after the damped sine wave y = sin(13pi/2*x)*pow(2, 10 * (x - 1)) + +/** \brief Elastic easing in, accelerate from zero + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_elast_in(float p); + +// Modeled after the damped sine wave y = sin(-13pi/2*(x + 1))*pow(2, -10x) + 1 +/** \brief Elastic easing out, decelerate to zero velocity + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_elast_out(float p); + +// Modeled after the piecewise exponentially-damped sine wave: +// y = (1/2)*sin(13pi/2*(2*x))*pow(2, 10 * ((2*x) - 1)) ; [0,0.5) +// y = (1/2)*(sin(-13pi/2*((2x-1)+1))*pow(2,-10(2*x-1)) + 2) ; [0.5, 1] +/** \brief Elastic easing in and out, accelerate to halfway, then decelerate + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_elast_in_out(float p); + +//Back + +// Modeled after the overshooting cubic y = x^3-x*sin(x*pi) +/** \brief Overshooting easing in, accelerate from zero + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_back_in(float p); + +// Modeled after overshooting cubic y = 1-((1-x)^3-(1-x)*sin((1-x)*pi)) +/** \brief Overshooting easing out, decelerate to zero velocity + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_back_out(float p); + +// Modeled after the piecewise overshooting cubic function: +// y = (1/2)*((2x)^3-(2x)*sin(2*x*pi)) ; [0, 0.5) +// y = (1/2)*(1-((1-x)^3-(1-x)*sin((1-x)*pi))+1) ; [0.5, 1] +/** \brief Overshooting easing in and out, accelerate to halfway, then decelerate + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_back_in_out(float p); + +//Bounce + +/** \brief Bouncing easing in, accelerate from zero + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_bounce_out(float p); + +/** \brief Bouncing easing out, decelerate to zero velocity + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_bounce_in(float p); + +/** \brief Bouncing easing in and out, accelerate to halfway, then decelerate + * + * \param p Input value, typically within the [0, 1] range + * \return Eased value + * + */ +float nema_ez_bounce_in_out(float p); + + +/** \brief Convenience function to perform easing between two values given number of steps, current step and easing function + * + * \param A Initial value within range [0, 1] + * \param B Finale value within range [0, 1] + * \param steps Total number of steps + * \param cur_step Current Step + * \param ez_func pointer to the desired easing function + * \return Eased value + * + */ + + +float nema_ez(float A, float B, float steps, float cur_step, float (*ez_func)(float p)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libs/nema_gfx/include/nema_error.h b/libs/nema_gfx/include/nema_error.h new file mode 100644 index 000000000..0bb922811 --- /dev/null +++ b/libs/nema_gfx/include/nema_error.h @@ -0,0 +1,69 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + +#ifndef NEMA_ERROR_H__ +#define NEMA_ERROR_H__ + +#include "nema_sys_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Error Handling + +#define NEMA_ERR_NO_ERROR (0x00000000U) /**< No error has occured */ +#define NEMA_ERR_SYS_INIT_FAILURE (0x00000001U) /**< System initialization failure */ +#define NEMA_ERR_GPU_ABSENT (0x00000002U) /**< Nema GPU is absent */ +#define NEMA_ERR_RB_INIT_FAILURE (0x00000004U) /**< Ring buffer initialization failure */ +#define NEMA_ERR_NON_EXPANDABLE_CL_FULL (0x00000008U) /**< Non expandable command list is full*/ +#define NEMA_ERR_CL_EXPANSION (0x00000010U) /**< Command list expansion error */ +#define NEMA_ERR_OUT_OF_GFX_MEMORY (0x00000020U) /**< Graphics memory is full */ +#define NEMA_ERR_OUT_OF_HOST_MEMORY (0x00000040U) /**< Host memory is full */ +#define NEMA_ERR_NO_BOUND_CL (0x00000080U) /**< There is no bound command list */ +#define NEMA_ERR_NO_BOUND_FONT (0x00000100U) /**< There is no bound font */ +#define NEMA_ERR_GFX_MEMORY_INIT (0x00000200U) /**< Graphics memory initialization failure */ +#define NEMA_ERR_DRIVER_FAILURE (0x00000400U) /**< Nema GPU Kernel Driver failure*/ +#define NEMA_ERR_MUTEX_INIT (0x00000800U) /**< Mutex initialization failure*/ +#define NEMA_ERR_INVALID_BO (0x00001000U) /**< Invalid buffer provided*/ +#define NEMA_ERR_INVALID_CL (0x00002000U) /**< Invalid CL provided*/ +#define NEMA_ERR_INVALID_CL_ALIGMENT (0x00004000U) /**< Invalid CL buffer alignment*/ +#define NEMA_ERR_NO_INIT (0x00008000U) /**< GFX uninitialised*/ + +/** \brief Return Error Id + * + * \return 0 if no error exists + * + */ +uint32_t nema_get_error(void); + + +#ifdef __cplusplus +} +#endif + +#endif // NEMA_ERROR_H__ diff --git a/libs/nema_gfx/include/nema_font.h b/libs/nema_gfx/include/nema_font.h new file mode 100644 index 000000000..7ce79db0b --- /dev/null +++ b/libs/nema_gfx/include/nema_font.h @@ -0,0 +1,184 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + + +#ifndef NEMA_FONT_H__ +#define NEMA_FONT_H__ + +#include "nema_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NEMA_ALIGNX_LEFT (0x00U) /**< Align horizontally to the left */ +#define NEMA_ALIGNX_RIGHT (0x01U) /**< Align horizontally to the right */ +#define NEMA_ALIGNX_CENTER (0x02U) /**< Align horizontally centered */ +#define NEMA_ALIGNX_JUSTIFY (0x03U) /**< Justify horizontally */ +#define NEMA_ALIGNX_MASK (0x03U) /**< Horizontal alignment mask */ +#define NEMA_ALIGNY_TOP (0x00U) /**< Align vertically to the top */ +#define NEMA_ALIGNY_BOTTOM (0x04U) /**< Align vertically to the bottom */ +#define NEMA_ALIGNY_CENTER (0x08U) /**< Align vertically centered */ +#define NEMA_ALIGNY_JUSTIFY (0x0cU) /**< Justify vertically */ +#define NEMA_ALIGNY_MASK (0x0cU) /**< Vertical alignment mask */ +#define NEMA_TEXT_WRAP (0x10U) /**< Use text wrapping */ + +typedef struct { + uint32_t left; /**< Neighbor character to the left of the current one (Unicode value) */ + int8_t x_offset; /**< Kerning offset (horizontally) */ +} nema_kern_pair_t; + +typedef struct { + uint32_t bitmapOffset; + uint8_t width; + uint8_t xAdvance; + int8_t xOffset; + int8_t yOffset; + uint32_t kern_offset; + uint8_t kern_length; +} nema_glyph_t; + +typedef struct { + int bitmapOffset; + uint8_t width; + uint8_t xAdvance; + int8_t xOffset; + int8_t yOffset; + int id; +} nema_glyph_indexed_t; + +typedef struct { + uint32_t first, last; + const nema_glyph_t *glyphs; +} nema_font_range_t; + +typedef struct { + nema_buffer_t bo; + const nema_font_range_t *ranges; + const int bitmap_size; + const uint8_t *bitmap; + uint32_t flags; + uint8_t xAdvance; //default xAdvance + uint8_t yAdvance; + uint8_t max_ascender; + uint8_t bpp; + const nema_kern_pair_t *kern_pairs; + const nema_glyph_indexed_t *indexed_glyphs; +} nema_font_t; + +/** \brief Bind the font to use in future nema_print() calls + * + * \param font Pointer to font + * + */ +void nema_bind_font(nema_font_t *font); + +/** \brief Get the bounding box's width and height of a string. + * + * \param str Pointer to string + * \param w Pointer to variable where width should be written + * \param h Pointer to variable where height should be written + * \param max_w Max allowed width + * \return Number of carriage returns + * + */ +int nema_string_get_bbox(const char *str, int *w, int *h, int max_w, uint32_t wrap); + +/** \brief Print pre-formatted text + * + * \param str Pointer to string + * \param x X coordinate of text-area's top-left corner + * \param y Y coordinate of text-area's top-left corner + * \param w Width of the text area + * \param h Height of the text area + * \param fg_col Foreground color of text + * \param align Alignment and wrapping mode + * + */ +void nema_print(const char *str, int x, int y, int w, int h, uint32_t fg_col, uint32_t align); + +/** \brief Print pre-formatted text + * + * \param *str Pointer to string + * \param *cursor_x X position of next character to be drawn. Usually initialized to 0 by the user and then updated internally by the library + * \param *cursor_y Y position of next character to be drawn. Usually initialized to 0 by the user and then updated internally by the library + * \param x X coordinate of text-area's top-left corner + * \param y Y coordinate of text-area's top-left corner + * \param w Width of the text area + * \param h Height of the text area + * \param fg_col Foreground color of text + * \param align Alignment and wrapping mode + * + */ +void nema_print_to_position(const char *str, int *pos_x, int *pos_y, int x, int y, int w, int h, uint32_t fg_col, uint32_t align); + + +/** \brief Print text (not formated) with indexed glyphs. Text is printed in a single line, from left to right + * + * \param ids Array with the glyphs indices + * \param id_count Count of the characters to be drawn + * \param x X coordinate of the text-area's top-left corner + * \param y Y coordinate of the text-area's top-left corner + * \param fg_col Foreground color of text + * + */ +void nema_print_indexed(const int *ids, int id_count, int x, int y, uint32_t fg_col); + +/** \brief Print a single character with indexed glyph + * + * \param id Array with the glyphs indices + * \param x X coordinate of the character's top-left corner + * \param y Y coordinate of the character's top-left corner + * \param fg_col Character's color + * + */ +void nema_print_char_indexed(const int id, int x, int y, uint32_t fg_col); + +/** \brief Returns the bounding box's width and height of a string with indexed glyphs + * + * \details The string must be specified as a single line text, due to the restriction + * that the characters are described by respective glyph indices. The height of the + * bounding box will be equal to the height of the bound font. + * + * \param ids Array with the glyphs indices + * \param id_count Count of the characters contained in the array with the glyphs indices + * \param w Pointer to variable where width should be written + * \param h Pointer to variable where height should be written + * \param max_w Maximum allowed width (if w is greater than this value, it will saturate to this) + */ +void nema_string_indexed_get_bbox(const int *ids, int id_count, int *w, int *h, int max_w); + +/** \brief Returns the horizontal advance (in pixels) of the bound font + * + */ +int nema_font_get_x_advance(); + +#ifdef __cplusplus +} +#endif + +#endif // NEMA_FONT_H__ diff --git a/libs/nema_gfx/include/nema_graphics.h b/libs/nema_gfx/include/nema_graphics.h new file mode 100644 index 000000000..00f240df7 --- /dev/null +++ b/libs/nema_gfx/include/nema_graphics.h @@ -0,0 +1,1017 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + + +#ifndef NEMA_GRAPHICS_H__ +#define NEMA_GRAPHICS_H__ + +#include "nema_sys_defs.h" +#include "nema_hal.h" +#include "nema_matrix3x3.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _img_obj_ { + nema_buffer_t bo; + uint16_t w; + uint16_t h; + int stride; + uint32_t color; + uint8_t format; + uint8_t sampling_mode; // NEMA_FILTER* +} img_obj_t; + +typedef img_obj_t nema_img_obj_t; + +typedef enum { + NEMA_NOTEX = -1, /**< No Texture */ + NEMA_TEX0 = 0, /**< Texture 0 */ + NEMA_TEX1 = 1, /**< Texture 1 */ + NEMA_TEX2 = 2, /**< Texture 2 */ + NEMA_TEX3 = 3 /**< Texture 3 */ +} nema_tex_t; + +#define NEMA_RGBX8888 0x00U /**< RGBX8888 */ +#define NEMA_RGBA8888 0x01U /**< RGBA8888 */ +#define NEMA_XRGB8888 0x02U /**< XRGB8888 */ +#define NEMA_ARGB8888 0x03U /**< ARGB8888 */ +#define NEMA_RGB565 0x04U /**< RGBA5650 */ +#define NEMA_RGBA5650 0x04U /**< RGBA5650 */ +#define NEMA_RGBA5551 0x05U /**< RGBA5551 */ +#define NEMA_RGBA4444 0x06U /**< RGBA4444 */ +#define NEMA_RGBA0800 0x07U /**< RGBA0800 */ +#define NEMA_A8 0x08U /**< RGBA0008 */ +#define NEMA_RGBA0008 0x08U /**< RGBA0008 */ +#define NEMA_L8 0x09U /**< L8 */ +#define NEMA_RGBA3320 0x38U /**< RGBA3320 (source only) */ +#define NEMA_RGB332 0x38U /**< RGBA3320 (source only) */ +#define NEMA_BW1 0x0CU /**< A1 (source only) */ +#define NEMA_A1 0x0CU /**< A1 (source only) */ +#define NEMA_L1 0x0BU /**< L1 (source only) */ +#define NEMA_UYVY 0x0DU /**< UYVY */ +#define NEMA_ABGR8888 0x0EU /**< ABGR8888 */ +#define NEMA_XBGR8888 0x0FU /**< XBGR8888 */ +#define NEMA_BGRA8888 0x10U /**< BGRA */ +#define NEMA_BGRX8888 0x11U /**< BGRX */ +#define NEMA_TSC4 0x12U /**< TSC4 */ +#define NEMA_TSC6 0x16U /**< TSC6 */ +#define NEMA_TSC6A 0x17U /**< TSC6A */ +#define NEMA_RV 0x18U /**< RV */ +#define NEMA_GU 0x19U /**< GU */ +#define NEMA_BY 0x1AU /**< BY */ +#define NEMA_YUV 0x1BU /**< YUV */ +#define NEMA_Z24_8 0x1cU /**< Z24_8 */ +#define NEMA_Z16 0x1dU /**< Z16 */ +#define NEMA_UV 0x1eU /**< UV */ +#define NEMA_A1LE 0x27U /**< A1LE (source only) */ +#define NEMA_A2LE 0x28U /**< A2LE (source only) */ +#define NEMA_A4LE 0x29U /**< A4LE (source only) */ +#define NEMA_L1LE 0x2AU /**< L1LE (source only) */ +#define NEMA_L2LE 0x2BU /**< L2LE (source only) */ +#define NEMA_L4LE 0x2CU /**< L4LE (source only) */ +#define NEMA_A2 0x30U /**< A2 (source only) */ +#define NEMA_A4 0x34U /**< A4 (source only) */ +#define NEMA_L2 0x31U /**< L2 (source only) */ +#define NEMA_L4 0x35U /**< L4 (source only) */ +#define NEMA_BGR24 0x39U /**< BGR24 */ +#define NEMA_RGB24 0x3CU /**< RGB24 */ +#define NEMA_RV10 0x3DU /**< RV-10bit */ +#define NEMA_GU10 0x3EU /**< GU-10bit */ +#define NEMA_BY10 0x3FU /**< BY-10bit */ +#define NEMA_RGBA2222 0x40U /**< RGBA2222 (Available if HW enabled - check HW manual) */ +#define NEMA_ABGR2222 0x41U /**< ABGR2222 (Available if HW enabled - check HW manual) */ +#define NEMA_BGRA2222 0x42U /**< BGRA2222 (Available if HW enabled - check HW manual) */ +#define NEMA_ARGB2222 0x43U /**< ARGB2222 (Available if HW enabled - check HW manual) */ +#define NEMA_AL88 0x44U /**< AL88 (Available if HW enabled - check HW manual) */ +#define NEMA_AL44 0x45U /**< AL44 (Available if HW enabled - check HW manual) */ +#define NEMA_ARGB1555 0x46U /**< ARGB1555 (Available if HW enabled - check HW manual) */ +#define NEMA_ARGB4444 0x47U /**< ARGB4444 (Available if HW enabled - check HW manual) */ +#define NEMA_BGRA5650 0x13U /**< BGRA5650 (Available if HW enabled - check HW manual) */ +#define NEMA_BGR565 0x13U /**< BGRA5650 (Available if HW enabled - check HW manual) */ +#define NEMA_BGRA5551 0x48U /**< BGRA5551 (Available if HW enabled - check HW manual) */ +#define NEMA_ABGR1555 0x49U /**< ABGR1555 (Available if HW enabled - check HW manual) */ +#define NEMA_BGRA4444 0x4aU /**< BGRA4444 (Available if HW enabled - check HW manual) */ +#define NEMA_ABGR4444 0x4bU /**< ABGR4444 (Available if HW enabled - check HW manual) */ +#define NEMA_TSC12 0x4cU /**< TSC12 (Available if HW enabled - check HW manual) */ +#define NEMA_TSC12A 0x4dU /**< TSC12A (Available if HW enabled - check HW manual) */ + +#define NEMA_DITHER 0x80U /**< Nema Dithering */ +#define NEMA_FORMAT_MASK 0x7FU /**< Format Mask */ + +typedef uint32_t nema_tex_format_t; + +//----------------------------------------------------------------------------------------------------------------------- + +// Texture Unit Parameters +//----------------------------------------------------------------------------------------- + // Filtering - 0:0 + //---------------------- +#define NEMA_FILTER_PS 0x00U /**< Point Sampling. */ +#define NEMA_FILTER_BL 0x01U /**< Bilinear filtering. */ + + // Wrapping Mode 3:2 + //---------------------- +#define NEMA_TEX_CLAMP (0x00U) /**< Clamp */ +#define NEMA_TEX_REPEAT (0x01U<<2) /**< Repeat */ +#define NEMA_TEX_BORDER (0x02U<<2) /**< Border */ +#define NEMA_TEX_MIRROR (0x03U<<2) /**< Mirror */ + + // Texture Coordinates Ordering 4:4 + //---------------------- +#define NEMA_TEX_MORTON_ORDER (0x10U) + + // Texture Coordinates Format 6:5 + //---------------------- +#define NEMA_TEX_RANGE_0_1 (0x1U<<5) /**< Interpolated Coordinates range: 0-1 */ +#define NEMA_TEX_LEFT_HANDED (0x1U<<6) /**< (0,0) is bottom left corner */ + +typedef uint8_t nema_tex_mode_t; + +// Triangle Culling +//----------------------------------------------------------------------------------------- +typedef enum { + NEMA_CULL_NONE = 0 , /**< Disable Triangle/Quadrilateral Culling */ + NEMA_CULL_CW = (1U<<28), /**< Cull clockwise Triangles/Quadrilaterals */ + NEMA_CULL_CCW = (1U<<29), /**< Cull anti-clockwise Triangles/Quadrilaterals */ + NEMA_CULL_ALL = NEMA_CULL_CW | NEMA_CULL_CCW /**< Cull all */ +} nema_tri_cull_t; + +// Rotation Modes +//----------------------------------------------------------------------------------------------------------------------- + +#define NEMA_ROT_000_CCW (0x0U) /**< No rotation */ +#define NEMA_ROT_090_CCW (0x1U) /**< Rotate 90 degrees counter-clockwise */ +#define NEMA_ROT_180_CCW (0x2U) /**< Rotate 180 degrees counter-clockwise */ +#define NEMA_ROT_270_CCW (0x3U) /**< Rotate 270 degrees counter-clockwise */ +#define NEMA_ROT_000_CW (0x0U) /**< No rotation */ +#define NEMA_ROT_270_CW (0x1U) /**< Rotate 270 degrees clockwise */ +#define NEMA_ROT_180_CW (0x2U) /**< Rotate 180 degrees clockwise */ +#define NEMA_ROT_090_CW (0x3U) /**< Rotate 90 degrees clockwise */ +#define NEMA_MIR_VERT (0x4U) /**< Mirror Vertically */ +#define NEMA_MIR_HOR (0x8U) /**< Mirror Horizontally */ + + +/** \brief Check if a known GPU is present + * + * \return -1 if no known GPU is present + * + */ +int nema_checkGPUPresence(void); + +// ------------------------------ TEXTURES ------------------------------------- + +/** \brief Program a Texture Unit + * + * \param texid Texture unit to be programmed + * \param addr_gpu Texture's address as seen by the GPU + * \param width Texture's width + * \param height Texture's height + * \param format Texture's format + * \param stride Texture's stride. If stride < 0, it's left to be calculated + * \param wrap_mode Wrap/Repeat mode to be used. When using 'repeat' or 'mirror', texture dimensions must be a power of two. Otherwise the behavior is undefined. + * + */ +void nema_bind_tex(nema_tex_t texid, uintptr_t addr_gpu, + uint32_t width, uint32_t height, + nema_tex_format_t format, int32_t stride, nema_tex_mode_t wrap_mode); + +/** \brief Set Texture Mapping default color + * + * \param color default color in 32-bit RGBA format + * \see nema_rgba() + * + */ +void nema_set_tex_color(uint32_t color); + +// ------------------------------ CONSTREGS ------------------------------------ + +/** \brief Write a value to a Constant Register of the GPU + * + * \param reg Constant Register to be written + * \param value Value to be written + * + */ +void nema_set_const_reg(int reg, uint32_t value); + +// --------------------------------- CLIP -------------------------------------- + +/** \brief Sets the drawing area's Clipping Rectangle + * + * \param x Clip Window top-left x coordinate + * \param y Clip Window minimum y + * \param w Clip Window width + * \param h Clip Window height + * + */ +void nema_set_clip(int32_t x, int32_t y, uint32_t w, uint32_t h); + +void nema_enable_gradient(int enable); + +void nema_enable_depth(int enable); + +/** \brief Enables MSAA per edge + * + * \param e0 Enable MSAA for edge 0 (vertices 0-1) + * \param e1 Enable MSAA for edge 1 (vertices 1-2) + * \param e2 Enable MSAA for edge 2 (vertices 2-3) + * \param e3 Enable MSAA for edge 3 (vertices 3-0) + * \return previous AA flags (may be ignored) + * + */ +uint32_t nema_enable_aa(uint8_t e0, uint8_t e1, uint8_t e2, uint8_t e3); + +// ------------------------------- DIRTY REGIONS ------------------------------------ + +/** \brief Returns the bounding rectangle of all the pixels that have been modified since its previous call. + * Available only on Nema|P and Nema|PVG GPUs. + * + * \param minx x coordinate of the upper left corner of the dirty region + * \param miny y coordinate of the upper left corner of the dirty region + * \param maxx x coordinate of the lower right corner of the dirty region + * \param maxy y coordinate of the lower right corner of the dirty region + * + */ +void nema_get_dirty_region(int *minx, int *miny, int *maxx, int *maxy); + +/** \brief Clear dirty region information - runs via the bound command-list + * Available only on Nema|P and Nema|PVG GPUs. + * + * \see nema_get_dirty_region() + * \see nema_clear_dirty_region_imm() + * + */ +void nema_clear_dirty_region(void); + +/** \brief Clear dirty region information immediately, no command-list involved + * Available only on Nema|P and Nema|PVG GPUs. + * + * \see nema_get_dirty_region() + * \see nema_clear_dirty_region() + * + */ +void nema_clear_dirty_region_imm(void); + +// -------------------------------- UTILS -------------------------------------- + +/** \brief Set triangle/quadrilateral culling mode + * + * \param cull Culling mode + * + */ +void nema_tri_cull(nema_tri_cull_t cull); + +/** \brief Return pixel size in bytes + * + * \param format Color format + * \return Pixel size in bytes + * + */ +int nema_format_size (nema_tex_format_t format); + +/** \brief Return stride in bytes + * + * \param format Color format + * \param wrap_mode Wrap/Repeat mode to be used. When using 'repeat' or 'mirror', texture dimensions must be a power of two. Otherwise the behavior is undefined. + * \param width Texture color format + * \return Stride in bytes + * + */ +int nema_stride_size(nema_tex_format_t format, nema_tex_mode_t wrap_mode, int width); + + +/** \brief Return texture size in bytes + * + * \param format Texture color format + * \param wrap_mode Wrap/Repeat mode to be used. When using 'repeat' or 'mirror', texture dimensions must be a power of two. Otherwise the behavior is undefined. + * \param width Texture width + * \param height Texture height + * \return Texture size in bytes + * + */ +int nema_texture_size(nema_tex_format_t format, nema_tex_mode_t wrap_mode, int width, int height); + +/** \brief Return Nema internal RGBA color + * + * \param R Red component + * \param G Green component + * \param B Blue component + * \param A Alpha component + * \return RGBA value + * + */ +uint32_t nema_rgba(unsigned char R, + unsigned char G, + unsigned char B, + unsigned char A); + +/** \brief Premultiply RGB channels with Alpha channel + * + * \param rgba RGBA color + * \return Premultiplied RGBA color + * + */ +uint32_t nema_premultiply_rgba(uint32_t rgba); + +/** \brief Initialize NemaGFX library + * + * \return negative value on error + * + */ +int nema_init(void); + +/** \brief Reinitialize NemaGFX library + * + * \details This function reinitializes the NemaGFX library after a GPU poweroff + * No memory allocation for ringbuffer etc is performed. + * + * \return negative value on error + * + */ +int nema_reinit(void); + +// ------------------------------- CONTEXT ------------------------------------- + +/** \brief Program Texture Unit with a foreground (source) texture (NEMA_TEX1) + * + * \param baseaddr_phys Address of the source texture, as seen by the GPU + * \param width Texture width + * \param height Texture hight + * \param format Texture format + * \param stride Texture stride. If negative, it's calculated internally. + * \param wrap_mode Wrap/Repeat mode to be used. When using 'repeat' or 'mirror', texture dimensions must be a power of two. Otherwise the behavior is undefined. + * + */ +void nema_bind_src_tex(uintptr_t baseaddr_phys, + uint32_t width, uint32_t height, + nema_tex_format_t format, int32_t stride, nema_tex_mode_t mode); + +/** \brief Program Texture Unit with a background texture ((NEMA_TEX2) + * + * \param baseaddr_phys Address of the source2 texture, as seen by the GPU + * \param width Texture width + * \param height Texture hight + * \param format Texture format + * \param stride Texture stride. If negative, it's calculated internally. + * \param wrap_mode Wrap/Repeat mode to be used. When using 'repeat' or 'mirror', texture dimensions must be a power of two. Otherwise the behavior is undefined. + * + */ +void nema_bind_src2_tex(uintptr_t baseaddr_phys, + uint32_t width, uint32_t height, + nema_tex_format_t format, int32_t stride, nema_tex_mode_t mode); + +/** \brief Program Texture Unit with a destination texture (NEMA_TEX0) + * + * \param baseaddr_phys Address of the destination texture, as seen by the GPU + * \param width Texture width + * \param height Texture hight + * \param format Texture format + * \param stride Texture stride. If negative, it's calculated internally. + * + */ +void nema_bind_dst_tex(uintptr_t baseaddr_phys, + uint32_t width, uint32_t height, + nema_tex_format_t format, int32_t stride); + +/** \brief Program Texture Unit with a lut/palette texture (NEMA_TEX2) and index texture (NEMA_TEX1_) + * + * \param baseaddr_phys Address of the index texture + * \param width Index texture width + * \param height Index texture hight + * \param format Index texture format + * \param stride Index texture stride. If negative, it's calculated internally. + * \param mode Index texture sampling mode. When using 'NEMA_TEX_REPEAT' or 'NEMA_TEX_MIRROR' wrapping mode, + * texture dimensions must be a power of two, otherwise the behavior is undefined. NEMA_FILTER_BL is not supported. + * \param palette_baseaddr_phys Address of the lut/palette texture + * \param palette_format lut/palette texture format + * + */ +void nema_bind_lut_tex( uintptr_t baseaddr_phys, + uint32_t width, uint32_t height, + nema_tex_format_t format, int32_t stride, nema_tex_mode_t mode, + uintptr_t palette_baseaddr_phys, + nema_tex_format_t palette_format); + +/** \brief Bind Depth Buffer + * + * \param baseaddr_phys Address of the depth buffer, as seen by the GPU + * \param width Buffer width + * \param height Buffer hight + * + */ +void nema_bind_depth_buffer(uintptr_t baseaddr_phys, + uint32_t width, uint32_t height); + +/** \private */ +// -------------------------------- DEPTH -------------------------------------- +void nema_set_depth(float start, float dx, float dy); + +// ------------------------------ GRADIENT ------------------------------------- +/** \private */ +void nema_set_gradient(float r_init, float g_init, float b_init, float a_init, + float r_dx, float r_dy, + float g_dx, float g_dy, + float b_dx, float b_dy, + float a_dx, float a_dy); + +// ------------------------------- DRAWING ------------------------------------- +/** \brief Clear destination texture with color + * + * \param rgba8888 32-bit RGBA color + * \see nema_rgba() + * + */ +void nema_clear(uint32_t rgba8888); + +/** \brief Clear depth buffer with specified value + * + * \param val Clear value + * + */ +void nema_clear_depth(uint32_t val); + +/** \brief Draw a colored line + * + * \param x0 x coordinate at the beginning of the line + * \param y0 y coordinate at the beginning of the line + * \param x1 x coordinate at the end of the line + * \param y1 y coordinate at the end of the line + * \param rgba8888 Color to be used + * \see nema_set_blend_fill() + * \see nema_rgba() + * + */ +void nema_draw_line(int x0, int y0, int x1, int y1, uint32_t rgba8888); + + +/** \brief Draw a line with width. Apply AA if available + * + * \param x0 x coordinate at the beginning of the line + * \param y0 y coordinate at the beginning of the line + * \param x1 x coordinate at the end of the line + * \param y1 y coordinate at the end of the line + * \param w line width + * \param rgba8888 Color to be used + * \see nema_draw_line() + * \see nema_set_blend_fill() + * \see nema_rgba() + * + */ +void +nema_draw_line_aa(float x0, float y0, float x1, float y1, float w, + uint32_t rgba8888); + +/** \brief Draw a colored circle with 1 pixel width + * + * \param x x coordinate of the circle's center + * \param y y coordinate of the circle's center + * \param r circle's radius + * \param rgba8888 Color to be used + * \see nema_set_blend_fill() + * \see nema_rgba() + * + */ +void nema_draw_circle(int x, int y, int r, uint32_t rgba8888); + +/** \brief Draw a colored circle with Anti-Aliasing (if available) and specified width + * + * \param x x coordinate of the circle's center + * \param y y coordinate of the circle's center + * \param r circle's radius + * \param w pencil width + * \param rgba8888 Color to be used + * \see nema_set_blend_fill() + * \see nema_rgba() + * + */ +void nema_draw_circle_aa(float x, float y, float r, float w, uint32_t rgba8888); + +/** \brief Draw a colored rectangle with rounded edges + * + * \param x0 x coordinate of the upper left vertex of the rectangle + * \param y0 y coordinate at the upper left vertex of the rectangle + * \param w width of the rectangle + * \param h height of the rectangle + * \param r corner radius + * \param rgba8888 + * \see nema_set_blend_fill() + * \see nema_rgba() + * + */ +void nema_draw_rounded_rect(int x0, int y0, int w, int h, int r, uint32_t rgba8888); + +/** \brief Draw a colored rectangle + * + * \param x x coordinate of the upper left vertex of the rectangle + * \param y y coordinate at the upper left vertex of the rectangle + * \param w width of the rectangle + * \param h height of the rectangle + * \param rgba8888 Color to be used + * \see nema_set_blend_fill() + * \see nema_rgba() + * + */ +void nema_draw_rect(int x, int y, int w, int h, uint32_t rgba8888); + +/** \brief Fill a circle with color + * + * \param x x coordinate of the circle's center + * \param y y coordinate of the circle's center + * \param r circle's radius + * \param rgba8888 Color to be used + * \see nema_set_blend_fill() + * \see nema_rgba() + * + */ +void nema_fill_circle(int x, int y, int r, uint32_t rgba8888); + +/** \brief Fill a circle with color, use Anti-Aliasing if available + * + * \param x x coordinate of the circle's center + * \param y y coordinate of the circle's center + * \param r circle's radius + * \param rgba8888 Color to be used + * \see nema_set_blend_fill() + * \see nema_rgba() + * + */ +void nema_fill_circle_aa(float x, float y, float r, uint32_t rgba8888); + +/** \brief Fill a triangle with color + * + * \param x0 x coordinate at the first vertex of the triangle + * \param y0 y coordinate at the first vertex of the triangle + * \param x1 x coordinate at the second vertex of the triangle + * \param y1 y coordinate at the second vertex of the triangle + * \param x2 x coordinate at the third vertex of the triangle + * \param y2 y coordinate at the third vertex of the triangle + * \param rgba8888 Color to be used + * \see nema_set_blend_fill() + * + */ +void nema_fill_triangle(int x0, int y0, int x1, int y1, int x2, int y2, uint32_t rgba8888); + +/** \brief Fill a rectangle with rounded edges with color + * + * \param x0 x coordinate of the upper left vertex of the rectangle + * \param y0 y coordinate at the upper left vertex of the rectangle + * \param w width of the rectangle + * \param h height of the rectangle + * \param r corner radius + * \param rgba8888 + * \see nema_set_blend_fill() + * \see nema_rgba() + * + */ +void nema_fill_rounded_rect(int x0, int y0, int w, int h, int r, uint32_t rgba8888); + +/** \brief Fill a rectangle with color + * + * \param x x coordinate of the upper left vertex of the rectangle + * \param y y coordinate at the upper left vertex of the rectangle + * \param w width of the rectangle + * \param h height of the rectangle + * \param rgba8888 Color to be used + * \see nema_set_blend_fill() + * \see nema_rgba() + * + */ +void nema_fill_rect(int x, int y, int w, int h, uint32_t rgba8888); + +/** \brief Fill a quadrilateral with color + * + * \param x0 x coordinate at the first vertex of the quadrilateral + * \param y0 y coordinate at the first vertex of the quadrilateral + * \param x1 x coordinate at the second vertex of the quadrilateral + * \param y1 y coordinate at the second vertex of the quadrilateral + * \param x2 x coordinate at the third vertex of the quadrilateral + * \param y2 y coordinate at the third vertex of the quadrilateral + * \param x3 x coordinate at the fourth vertex of the quadrilateral + * \param y3 y coordinate at the fourth vertex of the quadrilateral + * \param rgba8888 Color to be used + * \see nema_set_blend_fill() + * \see nema_rgba() + * + */ +void nema_fill_quad(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3, uint32_t rgba8888); + + +/** \brief Fill a rectangle with color (float coordinates) + * + * \param x x coordinate of the upper left vertex of the rectangle + * \param y y coordinate at the upper left vertex of the rectangle + * \param w width of the rectangle + * \param h height of the rectangle + * \param rgba8888 Color to be used + * \see nema_set_blend_fill() + * \see nema_rgba() + * + */ +void nema_fill_rect_f(float x, float y, float w, float h, uint32_t rgba8888); + + +/** \brief Fill a quadrilateral with color (float coordinates) + * + * \param x0 x coordinate at the first vertex of the quadrilateral + * \param y0 y coordinate at the first vertex of the quadrilateral + * \param x1 x coordinate at the second vertex of the quadrilateral + * \param y1 y coordinate at the second vertex of the quadrilateral + * \param x2 x coordinate at the third vertex of the quadrilateral + * \param y2 y coordinate at the third vertex of the quadrilateral + * \param x3 x coordinate at the fourth vertex of the quadrilateral + * \param y3 y coordinate at the fourth vertex of the quadrilateral + * \param rgba8888 Color to be used + * \see nema_set_blend_fill() + * \see nema_rgba() + * + */ +void nema_fill_quad_f(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, uint32_t rgba8888); + + +/** \brief Fill a triangle with color (float coordinates) + * + * \param x0 x coordinate at the first vertex of the triangle + * \param y0 y coordinate at the first vertex of the triangle + * \param x1 x coordinate at the second vertex of the triangle + * \param y1 y coordinate at the second vertex of the triangle + * \param x2 x coordinate at the third vertex of the triangle + * \param y2 y coordinate at the third vertex of the triangle + * \param rgba8888 Color to be used + * \see nema_set_blend_fill() + * + */ +void nema_fill_triangle_f(float x0, float y0, float x1, float y1, float x2, float y2, uint32_t rgba8888); + + +// ------------------------------- BLITTING ------------------------------------ + +/** \brief Blit source texture to destination texture + * + * \param x destination x coordinate + * \param y destination y coordinate + * \see nema_set_blend_fill() + * + */ +void nema_blit (int x, int y); + + +/** \brief Blit source texture to destination texture with rounded corners + * + * \param x destination x coordinate + * \param y destination y coordinate + * \param r destination corner radius + * \see nema_set_blend_fill() + * + */ +void nema_blit_rounded (int x, int y, int r); + +/** \brief Blit source texture to destination's specified rectangle (crop or wrap when needed) + * + * \param x destination x coordinate + * \param y destination y coordinate + * \param w destination width + * \param h destination height + * \see nema_set_blend_blit() + * + */ +void nema_blit_rect (int x, int y, int w, int h); + +/** \brief Blit part of a source texture to destination's specified rectangle (crop or wrap when needed) + * + * \param x destination x coordinate + * \param y destination y coordinate + * \param w destination width + * \param h destination height + * \param x source x coordinate + * \param y source y coordinate + * \see nema_blit_subrect() + * \see nema_set_blend_blit() + * + */ +void nema_blit_subrect(int dst_x, int dst_y, int w, int h, int src_x, int src_y); + +/** \brief Blit source texture to destination. Fit (scale) texture to specified rectangle. + * + * \param x destination x coordinate + * \param y destination y coordinate + * \param w destination width + * \param h destination height + * \see nema_set_blend_blit() + * + */ +void nema_blit_rect_fit(int x, int y, int w, int h); + + +/** \brief Blit part of source texture to destination. Fit (scale) texture to specified rectangle. + * + * \param x destination x coordinate + * \param y destination y coordinate + * \param w destination width + * \param h destination height + * \param x source x coordinate + * \param y source y coordinate + * \param w source width + * \param h source height + * \see nema_blit_rect_fit() + * \see nema_set_blend_blit() + * + */ +void nema_blit_subrect_fit( int dst_x, int dst_y, int dst_w, int dst_h, + int src_x, int src_y, int src_w, int src_h); + +/** \brief Rotate around pivot point and Blit source texture. + * + * \param cx destination rotation center x coordinate + * \param cy destination rotation center y coordinate + * \param px source pivot point x coordinate + * \param py source pivot point y coordinate + * \param degrees_cw degrees of clockwise rotation in range [0, 360] + * \see nema_set_blend_blit() + * + */ +void nema_blit_rotate_pivot( float cx, float cy, + float px, float py, float degrees_cw ); + +/** \brief Rotate and Blit source texture to destination. + * + * \param x destination x coordinate + * \param y destination y coordinate + * \param rotation Rotation to be done + * \see nema_set_blend_blit() + * + */ +void nema_blit_rotate(int x, int y, uint32_t rotation); + +/** \brief Rotate and Blit partial source texture to destination. + * + * \param sx source upper left x coordinate + * \param sy source upper left y coordinate + * \param sw source width of partial region + * \param sh source height of partial region + * \param x destination x coordinate + * \param y destination y coordinate + * \param rotation Rotation to be done + * \see nema_set_blend_blit() + * + */ +void nema_blit_rotate_partial(int sx, int sy, + int sw, int sh, + int x, int y, + uint32_t rotation); + + +/** \brief Blit source texture to destination. Fit texture to specified triangle. + * + * \param dx0 x coordinate at the first vertex of the triangle + * \param dy0 y coordinate at the first vertex of the triangle + * \param v0 in [0, 3] indicates the corner of the texture that fits to the first vertex of the triangle + * 0 _ _ 1 + * |_ _| + * 3 2 + * \param dx1 x coordinate at the second vertex of the triangle + * \param dy1 y coordinate at the second vertex of the triangle + * \param v1 in [0, 3] indicates the corner of the texture that fits to the second vertex of the triangle + * \param dx2 x coordinate at the third vertex of the triangle + * \param dy2 y coordinate at the third vertex of the triangle + * \param v2 in [0, 3] indicates the corner of the texture that fits to the third vertex of the triangle + * \see nema_set_blend_blit() + * + */ +void nema_blit_tri_fit (float dx0, float dy0, int v0, + float dx1, float dy1, int v1, + float dx2, float dy2, int v2); + +/** \brief Blit a triangular part of the source tecture to a triangular destination area + * + * \param dx0 x coordinate at the first vertex of the destination triangle + * \param dy0 y coordinate at the first vertex of the destination triangle + * \param dw0 w coordinate at the first vertex of the destination triangle + * \param dx1 x coordinate at the second vertex of the destination triangle + * \param dy1 y coordinate at the second vertex of the destination triangle + * \param dw1 w coordinate at the second vertex of the destination triangle + * \param dx2 x coordinate at the third vertex of the destination triangle + * \param dy2 y coordinate at the third vertex of the destination triangle + * \param dw2 w coordinate at the third vertex of the destination triangle + * \param sx0 x coordinate at the first vertex of the source triangle + * \param sy0 y coordinate at the first vertex of the source triangle + * \param sx1 x coordinate at the second vertex of the source triangle + * \param sy1 y coordinate at the second vertex of the source triangle + * \param sx2 x coordinate at the third vertex of the source triangle + * \param sy2 y coordinate at the third vertex of the source triangle + * \see nema_set_blend_blit() + * + */ +void nema_blit_tri_uv (float dx0, float dy0, float dw0, + float dx1, float dy1, float dw1, + float dx2, float dy2, float dw2, + float sx0, float sy0, + float sx1, float sy1, + float sx2, float sy2 + ); + +/** \brief Blit source texture to destination. Fit texture to specified quadrilateral. + * + * \param dx0 x coordinate at the first vertex of the quadrilateral + * \param dy0 y coordinate at the first vertex of the quadrilateral + * \param dx1 x coordinate at the second vertex of the quadrilateral + * \param dy1 y coordinate at the second vertex of the quadrilateral + * \param dx2 x coordinate at the third vertex of the quadrilateral + * \param dy2 y coordinate at the third vertex of the quadrilateral + * \param dx3 x coordinate at the fourth vertex of the quadrilateral + * \param dy3 y coordinate at the fourth vertex of the quadrilateral + * \see nema_set_blend_blit() + * \see nema_blit_subrect_quad_fit() + * + */ +void nema_blit_quad_fit (float dx0, float dy0, + float dx1, float dy1, + float dx2, float dy2, + float dx3, float dy3); + +/** \brief Blit source texture to destination. Fit rectangulare area of texture to specified quadrilateral. + * + * \param dx0 x coordinate at the first vertex of the quadrilateral + * \param dy0 y coordinate at the first vertex of the quadrilateral + * \param dx1 x coordinate at the second vertex of the quadrilateral + * \param dy1 y coordinate at the second vertex of the quadrilateral + * \param dx2 x coordinate at the third vertex of the quadrilateral + * \param dy2 y coordinate at the third vertex of the quadrilateral + * \param dx3 x coordinate at the fourth vertex of the quadrilateral + * \param dy3 y coordinate at the fourth vertex of the quadrilateral + * \param sx x coordinate of the top left corner of the texture's rectangular area to be blitted + * \param sy y coordinate of the top left corner of the texture's rectangular area to be blitted + * \param sw width of the texture's rectangular area to be blitted + * \param sh height of the texture's rectangular area to be blitted + * \see nema_set_blend_blit() + * \see nema_blit_quad_fit() + * + */ +void nema_blit_subrect_quad_fit(float dx0, float dy0, + float dx1, float dy1, + float dx2, float dy2, + float dx3, float dy3, + int sx, int sy, + int sw, int sh); + +/** \brief Blit source texture to destination. Use the matrix provided by the user. + * + * \param dx0 x coordinate at the first vertex of the quadrilateral + * \param dy0 y coordinate at the first vertex of the quadrilateral + * \param dx1 x coordinate at the second vertex of the quadrilateral + * \param dy1 y coordinate at the second vertex of the quadrilateral + * \param dx2 x coordinate at the third vertex of the quadrilateral + * \param dy2 y coordinate at the third vertex of the quadrilateral + * \param dx3 x coordinate at the fourth vertex of the quadrilateral + * \param dy3 y coordinate at the fourth vertex of the quadrilateral + * \param m 3x3 matrix (screen coordinates to texture coordinates) + * \see nema_set_blend_blit() + * + */ +void nema_blit_quad_m(float dx0, float dy0, + float dx1, float dy1, + float dx2, float dy2, + float dx3, float dy3, nema_matrix3x3_t m); + + + + +/** \brief Enable breakpoints + * + * \see nema_brk_disable() + * + */ +void nema_brk_enable(void); + +/** \brief Disable breakpoints + * + * \see nema_brk_enable() + * + */ +void nema_brk_disable(void); + + +/** \brief Add a breakpoint to the current Command List + * + * \return Breakpoint ID + * + */ +int nema_brk_add(void); + +/** \brief Add a breakpoint to the current Command List + * + * \param brk_id Breakpoint ID to wait for. If zero (0), wait until next Breakpoint + * \return ID of reached Breakpoint + * + */ +int nema_brk_wait(int brk_id); + +/** \brief Instruct the GPU to resume execution + * + * + */ +void nema_brk_continue(void); + +/** \brief Enable external hold signals + * + * \param hold_id Hold signals to be enabled [0-3] + * \see nema_ext_hold_disable() + * + */ +void nema_ext_hold_enable(uint32_t hold_id); + +/** \brief Disable external hold signals + * + * \param hold_id Hold signals to be disabled [0-3] + * \see nema_ext_hold_enable() + * + */ +void nema_ext_hold_disable(uint32_t hold_id); + +/** \brief Enable Interrupt Request when GPU reaches hold point + * + * \param hold_id Hold signals' IRQ to be enabled [0-3] + * \see nema_ext_hold_disable() + * + */ +void nema_ext_hold_irq_enable(uint32_t hold_id); + +/** \brief Disable external hold signals + * + * \param hold_id Hold signals' IRQ to be disabled [0-3] + * \see nema_ext_hold_enable() + * + */ +void nema_ext_hold_irq_disable(uint32_t hold_id); + + +/** \brief Assert hold signals internally via a Command List + * + * \param hold_id Hold signal to be asserted + * \param stop If not zero, force Command List Processor to wait for FLAG to be deasserted + * \see nema_ext_hold_deassert() + * + */ +void nema_ext_hold_assert(uint32_t hold_id, int stop); + +/** \brief Dessert hold signals internally via a Command List + * + * \param hold_id Hold signal to be deasserted + * \see nema_ext_hold_assert() + * + */ +void nema_ext_hold_deassert(uint32_t hold_id); + +/** \brief Assert hold signals from the CPU (no Command List) + * + * \param hold_id Hold signal to be asserted + * \see nema_ext_hold_deassert() + * + */ +void nema_ext_hold_assert_imm(uint32_t hold_id); + +/** \brief Dessert hold signals from the CPU (no Command List) + * + * \param hold_id Hold signal to be deasserted + * \see nema_ext_hold_assert() + * + */ +void nema_ext_hold_deassert_imm(uint32_t hold_id); + +/** \brief Check for which architeture is the library compiled + * + * \return Returns string with the architecture name + * + */ +const char* nema_get_sw_device_name(void); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libs/nema_gfx/include/nema_hal.h b/libs/nema_gfx/include/nema_hal.h new file mode 100644 index 000000000..af2389844 --- /dev/null +++ b/libs/nema_gfx/include/nema_hal.h @@ -0,0 +1,218 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + + +#ifndef NEMA_HAL_H__ +#define NEMA_HAL_H__ + +#include "nema_sys_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct nema_buffer_t_ { + int size; /**< Size of buffer */ + int fd; /**< File Descriptor of buffer */ + void *base_virt; /**< Virtual address of buffer */ + uintptr_t base_phys; /**< Physical address of buffer */ +} nema_buffer_t; + +/** \brief Initialize system. Implementor defined. Called in nema_init() + * + * \param void + * \return 0 if no errors occurred + * \see nema_init() + * + */ +int32_t nema_sys_init(void); + + +/** \brief Wait for interrupt from the GPU + * + * \param void + * \return 0 on success + * + */ +int nema_wait_irq(void); + +/** \brief Wait for a Command List to finish + * + * \param cl_id Command List ID + * \return 0 on success + * + */ +int nema_wait_irq_cl(int cl_id); + +/** \brief Wait for a Breakpoint + * + * \param cl_id Breakpoint ID + * \return 0 on success + * + */ +int nema_wait_irq_brk(int brk_id); + +/** \brief Read Hardware register + * + * \param reg Register to read + * \return Value read from the register + * \see nema_reg_write + * + */ +uint32_t nema_reg_read(uint32_t reg); + +/** \brief Write Hardware Register + * + * \param reg Register to write + * \param value Value to be written + * \return void() + * \see nema_reg_read() + * + */ +void nema_reg_write(uint32_t reg, uint32_t value); + +/** \brief Create memory buffer + * + * \param size Size of buffer in bytes + * \return nema_buffer_t struct + * + */ +nema_buffer_t nema_buffer_create(int size); + +/** \brief Create memory buffer at a specific pool + * + * \param pool ID of the desired memory pool + * \param size Size of buffer in bytes + * \return nema_buffer_t struct + * + */ +nema_buffer_t nema_buffer_create_pool(int pool, int size); + +/** \brief Maps buffer + * + * \param bo Pointer to buffer struct + * \return Virtual pointer of the buffer (same as in bo->base_virt) + * + */ +void *nema_buffer_map(nema_buffer_t *bo); + +/** \brief Unmaps buffer + * + * \param bo Pointer to buffer struct + * \return void + * + */ +void nema_buffer_unmap(nema_buffer_t *bo); + +/** \brief Destroy/deallocate buffer + * + * \param bo Pointer to buffer struct + * \return void + * + */ +void nema_buffer_destroy(nema_buffer_t *bo); + +/** \brief Get physical (GPU) base address of a given buffer + * + * \param bo Pointer to buffer struct + * \return Physical base address of a given buffer + * + */ +uintptr_t nema_buffer_phys(nema_buffer_t *bo); + +/** \brief Write-back buffer from cache to main memory + * + * \param bo Pointer to buffer struct + * \return void + * + */ +void nema_buffer_flush(nema_buffer_t * bo); + +/** \brief Allocate memory for CPU to use (typically, standard malloc() is called) + * + * \param size Size in bytes + * \return Pointer to allocated memory (virtual) + * \see nema_host_free() + * + */ +void *nema_host_malloc(size_t size); + +/** \brief Free memory previously allocated with nema_host_malloc() + * + * \param ptr Pointer to allocated memory (virtual) + * \return void + * \see nema_host_malloc() + * + */ +void nema_host_free(void *ptr ); + +/** \private */ +typedef struct nema_ringbuffer_t_ { + nema_buffer_t bo; + int offset; //number of 32-bit entries + int last_submission_id; +} nema_ringbuffer_t; + + +/** \brief Initialize Ring Buffer. Should be called from inside nema_sys_init(). + * This is a private function, the user should never call it. + * + * \param *rb Pointer to nema_ring_buffer_t struct + * \param reset Resets the Ring Buffer if non-zero + * \return Negative number on error + * \see nema_sys_init() + * + */ +/** \private */ +int nema_rb_init(nema_ringbuffer_t *rb, int reset); + +#define MUTEX_RB 0 +#define MUTEX_MALLOC 1 +#define MUTEX_FLUSH 2 +#define MUTEX_MAX 2 + +/** \brief Mutex Lock for multiple processes/threads + * + * \param MUTEX_RB or MUTEX_MALLOC + * \return int + * + */ +int nema_mutex_lock(int mutex_id); + +/** \brief Mutex Unlock for multiple processes/threads + * + * \param MUTEX_RB or MUTEX_MALLOC + * \return int + * + */ +int nema_mutex_unlock(int mutex_id); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libs/nema_gfx/include/nema_interpolators.h b/libs/nema_gfx/include/nema_interpolators.h new file mode 100644 index 000000000..f3058a41e --- /dev/null +++ b/libs/nema_gfx/include/nema_interpolators.h @@ -0,0 +1,122 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + + +#ifndef _NEMA_INTERPOLATORS_H_ +#define _NEMA_INTERPOLATORS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nema_sys_defs.h" + +typedef struct _color_var_t { + float r; /**< Red */ + float g; /**< Green */ + float b; /**< Blue */ + float a; /**< Alpha */ +} color_var_t; + +/** \brief Interpolate color gradient for rectangle + * + * \param x0 x coordinate of the upper left vertex of the rectangle + * \param y0 y coordinate at the upper left vertex of the rectangle + * \param w width of the rectangle + * \param h height of the rectangle + * \param col0 color for the first vertex + * \param col1 color for the second vertex + * \param col1 color for the third vertex + * + */ +void nema_interpolate_rect_colors(int x0, int y0, int w, int h, color_var_t* col0, color_var_t* col1, color_var_t* col2); + + +/** \brief Interpolate color gradient for triangle + * + * \details The upper left vertex of the triangle to be drawn + * must be in the vertex arguments as well. In addition, if + * clipping is applied for rendering a triangle with gradient, + * the upper left vertex must be within the clipping area. + * \param x0 x coordinate at the first vertex of the triangle + * \param y0 y coordinate at the first vertex of the triangle + * \param x1 x coordinate at the second vertex of the triangle + * \param y1 y coordinate at the second vertex of the triangle + * \param x2 x coordinate at the third vertex of the triangle + * \param y2 y coordinate at the third vertex of the triangle + * \param col0 color for the first vertex + * \param col1 color for the second vertex + * \param col1 color for the third vertex + * + */ +void nema_interpolate_tri_colors(float x0, float y0, float x1, float y1, float x2, float y2, color_var_t* col0, color_var_t* col1, color_var_t* col2); + +/** \brief Interpolate depth buffer values for triangle + * + * \param x0 x coordinate at the first vertex of the triangle + * \param y0 y coordinate at the first vertex of the triangle + * \param z0 z coordinate at the first vertex of the triangle + * \param x1 x coordinate at the second vertex of the triangle + * \param y1 y coordinate at the second vertex of the triangle + * \param z1 z coordinate at the second vertex of the triangle + * \param x2 x coordinate at the third vertex of the triangle + * \param y2 y coordinate at the third vertex of the triangle + * \param z2 z coordinate at the third vertex of the triangle + * + */ +void nema_interpolate_tri_depth(float x0, float y0, float z0, float x1, float y1, float z1, float x2, float y2, float z2); + +/** \brief Interpolate texture values for triangle + * + * \param x0 x coordinate at the first vertex of the triangle + * \param y0 y coordinate at the first vertex of the triangle + * \param w0 w coordinate at the first vertex of the triangle + * \param tx0 x texture coordinate at the first vertex of the triangle + * \param ty0 y texture coordinate at the first vertex of the triangle + * \param x1 x coordinate at the second vertex of the triangle + * \param y1 y coordinate at the second vertex of the triangle + * \param w1 w coordinate at the second vertex of the triangle + * \param tx1 x texture coordinate at the second vertex of the triangle + * \param ty1 y texture coordinate at the second vertex of the triangle + * \param x2 x coordinate at the third vertex of the triangle + * \param y2 y coordinate at the third vertex of the triangle + * \param w2 w coordinate at the third vertex of the triangle + * \param tx2 x texture coordinate at the third vertex of the triangle + * \param ty2 x texture coordinate at the third vertex of the triangle + * \param tex_width texture width + * \param tex_height texture height + * + */ +void nema_interpolate_tx_ty(float x0, float y0, float w0, float tx0, float ty0, + float x1, float y1, float w1, float tx1, float ty1, + float x2, float y2, float w2, float tx2, float ty2, + int tex_width, int tex_height ); +#ifdef __cplusplus +} +#endif + +#endif // _NEMA_INTERPOLATORS_H_ diff --git a/libs/nema_gfx/include/nema_math.h b/libs/nema_gfx/include/nema_math.h new file mode 100644 index 000000000..abc3d4ce4 --- /dev/null +++ b/libs/nema_gfx/include/nema_math.h @@ -0,0 +1,278 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + + +#ifndef NEMA_MATH_H__ +#define NEMA_MATH_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define NEMA_E 2.71828182845904523536f /**< e */ +#define NEMA_LOG2E 1.44269504088896340736f /**< log2(e) */ +#define NEMA_LOG10E 0.434294481903251827651f /**< log10(e) */ +#define NEMA_LN2 0.693147180559945309417f /**< ln(2) */ +#define NEMA_LN10 2.30258509299404568402f /**< ln(10) */ +#define NEMA_PI 3.14159265358979323846f /**< pi */ +#define NEMA_PI_2 1.57079632679489661923f /**< pi/2 */ +#define NEMA_PI_4 0.785398163397448309616f /**< pi/4 */ +#define NEMA_1_PI 0.318309886183790671538f /**< 1/pi */ +#define NEMA_2_PI 0.636619772367581343076f /**< 2/pi */ +#define NEMA_2_SQRTPI 1.12837916709551257390f /**< 2/sqrt(pi) */ +#define NEMA_SQRT2 1.41421356237309504880f /**< sqrt(2) */ +#define NEMA_SQRT1_2 0.707106781186547524401f /**< 1/sqrt(2) */ + +/** \brief Fast sine approximation of a given angle + * + * \param angle_degrees Angle in degrees + * \return Sine of the given angle + * + */ +float nema_sin(float angle_degrees); + + +/** \brief Fast cosine approximation of a given angle + * + * \param angle_degrees Angle in degrees + * \return Cosine of the given angle + * + */ +float nema_cos(float angle_degrees); + +/** \brief Fast tangent approximation of a given angle + * + * \param angle_degrees Angle in degrees + * \return Tangent of the given angle + * + */ +float nema_tan(float angle_degrees); + + +/** \brief Fast sine approximation of a given angle + * + * \param angle_radians Angle in radians + * \return Sine of the given angle + * + */ +float nema_sin_r(float angle_radians); + + +/** \brief Fast cosine approximation of a given angle + * + * \param angle_radians Angle in radians + * \return Cosine of the given angle + * + */ +float nema_cos_r(float angle_radians); + +/** \brief Fast tangent approximation of a given angle + * + * \param angle_radians Angle in radians + * \return Tangent of the given angle + * + */ +float nema_tan_r(float angle_radians); + +/** \brief Fast arc tangent approximation of a y/x + * + * \param y value + * \param x value + * \return Arc tangent of the given y/x in degrees + * + */ +float nema_atan2(float y, float x); + +/** \brief Fast arc tangent approximation of a y/x + * + * \param y value + * \param x value + * \return Arc tangent of the given y/x in radians + * + */ +float nema_atan2_r(float y, float x); + +/** \brief A rough approximation of x raised to the power of y. USE WITH CAUTION! + * + * \param x base value. Must be non negative. + * \param y power value + * \return the result of raising x to the power y + * + */ +float nema_pow(float x, float y); + +/** \brief A rough approximation of the square root of x. USE WITH CAUTION! + * + * \param x X value. Must be non negative + * \param + * \return The square root of x + * + */ +float nema_sqrt(float x); + + +/** \brief A floating-point approximation of the inverse tangent of x + * + * \param x X value + * \return Inverse tangent (angle) of x in degrees + * + */ +float nema_atan(float x); + +/** \brief Find the minimum of two values + * + * \param a First value + * \param b Second value + * \return The minimum of a and b + * + */ +#define nema_min2(a,b) (((a)<(b))?( a):(b)) + +/** \brief Find the maximum of two values + * + * \param a First value + * \param b Second value + * \return The maximum of a and b + * + */ +#define nema_max2(a,b) (((a)>(b))?( a):(b)) + +/** \brief Clamp value + * + * \param val Value to clamp + * \param min Minimum value + * \param max Minimum value + * \return Clamped value + * + */ +#define nema_clamp(val, min, max) nema_min2((max), nema_max2((min), (val))) + +/** \brief Calculate the absolute value of int + * + * \param a Value + * \return The absolute value of a + * + */ +#define nema_abs(a) (((a)< 0 )?(-(a)):(a)) + +/** \brief Calculate the absolute value of float + * + * \param a Value + * \return The absolute value of a + * + */ +#define nema_absf(a) (((a)< 0.f )?(-(a)):(a)) + + +/** \brief Compare two floats + * + * \param x First float + * \param y Second float + * \return 1 if x == y, 0 if x != y + * + */ +#define nema_floats_equal(x, y) (nema_absf((x) - (y)) <= 0.00001f * nema_min2(nema_absf(x), nema_absf(y))) + +/** \brief Checks if value x is zero + * + * \param x X value + * \return 1 if x == 0, 0 if x != 0 + * + */ +#define nema_float_is_zero(x) (nema_absf(x) <= 0.00001f) + +/** \brief Convert degrees to radians + * + * \param d Angle in degrees + * \return Angle in radians + * + */ +#define nema_deg_to_rad(d) (0.0174532925199f * (d)) //rad = deg * pi / 180 + +/** \brief Convert radians to degries + * + * \param r Angle in radians + * \return Angle in degrees + * + */ +#define nema_rad_to_deg(r) (57.295779513f * (r)) //deg = rad * 180 / pi + +/** \brief Convert integer to 16.16 fixed point + * + * \param a Value to be converted + * \return 16.16 fixed point value + * + */ +#define nema_i2fx(a) ((a)*0x10000) + +/** \brief Convert float to 16.16 fixed point + * + * \param a Value to be converted + * \return 16.16 fixed point value + * + */ +// #define nema_f2fx(a) ((int)(((a)*((float)0x10000)+0.5f))) +int nema_f2fx(float f); // ((int)(((a)*((float)0x10000)+0.5f))) + +/** \brief Floor function + * + * \param a Value to be floored + * \return floored value + * + */ +#define nema_floor(f) ((int)(f) - ( (int)(f) > (f) )) + +/** \brief Ceiling function + * + * \param a Value to be ceiled + * \return ceiled value + * + */ +#define nema_ceil(f) ((int)(f) + ( (int)(f) < (f) )) + +/** \brief Truncate function + * + * \param x Value to be truncated + * \return truncated value + * + */ +#define nema_truncf(x) (x < 0.0f ? nema_ceil(x) : nema_floor(x)) + +/** \brief Float Modulo function + * + * \param x Dividend + * \param y Divisor + * \return Remainder + * + */ +#define nema_fmod(x, y) (x - nema_truncf(x / y) * y) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libs/nema_gfx/include/nema_matrix3x3.h b/libs/nema_gfx/include/nema_matrix3x3.h new file mode 100644 index 000000000..7686065b2 --- /dev/null +++ b/libs/nema_gfx/include/nema_matrix3x3.h @@ -0,0 +1,230 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + + +#ifndef NEMA_MATRIX3X3_H__ +#define NEMA_MATRIX3X3_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef float nema_matrix3x3_t[3][3]; + + +/** \brief Load Identity Matrix + * + * \param m Matrix to be loaded + * + */ +void nema_mat3x3_load_identity(nema_matrix3x3_t m); + + +/** \brief Copy matrix _m to matrix m + * + * \param m Destination matrix + * \param m Source matrix + * + */ +void +nema_mat3x3_copy(nema_matrix3x3_t m, nema_matrix3x3_t _m); + +/** \brief Apply translate transformation + * + * \param m Matrix to apply transformation + * \param tx X translation factor + * \param ty Y translation factor + * + */ +void nema_mat3x3_translate (nema_matrix3x3_t m, float tx, float ty); + +/** \brief Apply scale transformation + * + * \param m Matrix to apply transformation + * \param sx X scaling factor + * \param sy Y scaling factor + * + */ +void nema_mat3x3_scale (nema_matrix3x3_t m, float sx, float sy); + +/** \brief Apply shear transformation + * + * \param m Matrix to apply transformation + * \param shx X shearing factor + * \param shy Y shearing factor + * + */ +void nema_mat3x3_shear (nema_matrix3x3_t m, float shx, float shy); + +/** \brief Apply mirror transformation + * + * \param m Matrix to apply transformation + * \param mx if non-zero, mirror horizontally + * \param my if non-zero, mirror vertically + * + */ +void nema_mat3x3_mirror (nema_matrix3x3_t m, int mx, int my); + +/** \brief Apply rotation transformation + * + * \param m Matrix to apply transformation + * \param angle_degrees Angle to rotate in degrees + * + */ +void nema_mat3x3_rotate (nema_matrix3x3_t m, float angle_degrees); + +/** \brief Apply rotation transformation + * + * \param m Matrix to apply transformation + * \param cosa Cos of angle to rotate + * \param sina Sin of angle to rotate + * + */ +void +nema_mat3x3_rotate2(nema_matrix3x3_t m, float cosa, float sina); + + +/** \brief Multiply two 3x3 matrices ( m = m*_m) + * + * \param m left matrix, will be overwritten by the result + * \param _m right matrix + * + */ +void nema_mat3x3_mul(nema_matrix3x3_t m, nema_matrix3x3_t _m); + +/** \brief Multiply vector with matrix + * + * \param m Matrix to multiply with + * \param x Vector x coefficient + * \param y Vector y coefficient + * + */ +void nema_mat3x3_mul_vec(nema_matrix3x3_t m, float *x, float *y); + +/** \brief Multiply vector with affine matrix + * + * \param m Matrix to multiply with + * \param x Vector x coefficient + * \param y Vector y coefficient + * + */ +void nema_mat3x3_mul_vec_affine(nema_matrix3x3_t m, float *x, float *y); + +/** \brief Calculate adjoint + * + * \param m Matrix + * + */ +void nema_mat3x3_adj(nema_matrix3x3_t m); + + +/** \brief Divide matrix with scalar value + * + * \param m Matrix to divide + * \param s scalar value + * + */ +void nema_mat3x3_div_scalar(nema_matrix3x3_t m, float s); + +/** \brief Invert matrix + * + * \param m Matrix to invert + * + */ +int nema_mat3x3_invert(nema_matrix3x3_t m); + +/** \private */ +int nema_mat3x3_square_to_quad(float dx0, float dy0, + float dx1, float dy1, + float dx2, float dy2, + float dx3, float dy3, + nema_matrix3x3_t m); + +/** \brief Map rectangle to quadrilateral + * + * \param width Rectangle width + * \param height Rectangle height + * \param sx0 x coordinate at the first vertex of the quadrilateral + * \param sy0 y coordinate at the first vertex of the quadrilateral + * \param sx1 x coordinate at the second vertex of the quadrilateral + * \param sy1 y coordinate at the second vertex of the quadrilateral + * \param sx2 x coordinate at the third vertex of the quadrilateral + * \param sy2 y coordinate at the third vertex of the quadrilateral + * \param sx3 x coordinate at the fourth vertex of the quadrilateral + * \param sy3 y coordinate at the fourth vertex of the quadrilateral + * \param m Mapping matrix + * + */ +int nema_mat3x3_quad_to_rect(int width, int height, + float sx0, float sy0, + float sx1, float sy1, + float sx2, float sy2, + float sx3, float sy3, + nema_matrix3x3_t m); + +/** \brief Apply rotation around a pivot point + * + * \param m Matrix to apply transformation + * \param angle_degrees Angle to rotate in degrees + * \param x X coordinate of the pivot point + * \param y Y coordinate of the pivot point + * + */ +void nema_mat3x3_rotate_pivot(nema_matrix3x3_t m, float angle_degrees, + float x, float y); + +/** \brief Apply scale and then rotation around a pivot point + * + * \param m Matrix to apply transformation +* \param sx X scaling factor + * \param sy Y scaling factor + * \param angle_degrees Angle to rotate in degrees + * \param x X coordinate of the pivot point + * \param y Y coordinate of the pivot point + * + */ +void nema_mat3x3_scale_rotate_pivot(nema_matrix3x3_t m, + float sx, float sy, + float angle_degrees, float x, float y); + + +/** \brief Copy matrix _m to matrix m + * + * \param m Destination matrix + * \param m Source matrix + * + */ + +void +nema_mat3x3_copy(nema_matrix3x3_t m, nema_matrix3x3_t _m); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libs/nema_gfx/include/nema_matrix4x4.h b/libs/nema_gfx/include/nema_matrix4x4.h new file mode 100644 index 000000000..2b968a6b1 --- /dev/null +++ b/libs/nema_gfx/include/nema_matrix4x4.h @@ -0,0 +1,232 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + + +#ifndef NEMA_MATRIX4X4_H__ +#define NEMA_MATRIX4X4_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef float nema_matrix4x4_t[4][4]; + + +/** \brief Load a 4x4 Identity Matrix + * + * \param m Matrix to be loaded + * + */ +void nema_mat4x4_load_identity(nema_matrix4x4_t m); + +/** \brief Multiply two 4x4 matrices + * + * \param m Result Matrix + * \param m_l Left operand + * \param m_r Right operand + * + */ +void nema_mat4x4_mul(nema_matrix4x4_t m, + nema_matrix4x4_t m_l, + nema_matrix4x4_t m_r); + + +void nema_mat4x4_copy(nema_matrix4x4_t m_l, + nema_matrix4x4_t m_r); + +/** \brief Multiply a 4x1 vector with a 4x4 matrix + * + * \param m Matrix to be multiplied + * \param x Vector first element + * \param y Vector second element + * \param z Vector third element + * \param w Vector forth element + * + */ +void nema_mat4x4_mul_vec(nema_matrix4x4_t m, float *x, float *y, float *z, float *w); + +// ------------------------------------------------------------------------------------ +// Object Transformation - ModelView Matrix +// Object Coordinates to Eye Coordinates +// ------------------------------------------------------------------------------------ + +/** \brief Apply translate transformation + * + * \param m Matrix to apply transformation + * \param tx X translation factor + * \param ty Y translation factor + * \param tz Z translation factor + * + */ +void nema_mat4x4_translate(nema_matrix4x4_t m, float tx, float ty, float tz); + +/** \brief Apply scale transformation + * + * \param m Matrix to apply transformation + * \param sx X scaling factor + * \param sy Y scaling factor + * \param sz Z scaling factor + * + */ +void nema_mat4x4_scale(nema_matrix4x4_t m, float sx, float sy, float sz); + +/** \brief Apply rotate transformation around X axis + * + * \param m Matrix to apply transformation + * \param angle_degrees Angle to rotate in degrees + * + */ +void nema_mat4x4_rotate_X (nema_matrix4x4_t m, float angle_degrees); + +/** \brief Apply rotate transformation around Y axis + * + * \param m Matrix to apply transformation + * \param angle_degrees Angle to rotate in degrees + * + */ +void nema_mat4x4_rotate_Y (nema_matrix4x4_t m, float angle_degrees); + +/** \brief Apply rotate transformation around Z axis + * + * \param m Matrix to apply transformation + * \param angle_degrees Angle to rotate in degrees + * + */ +void nema_mat4x4_rotate_Z (nema_matrix4x4_t m, float angle_degrees); + +// ------------------------------------------------------------------------------------ +// Scene Transformation/Frustum - Projection Matrix +// Eye Coordinates to Clip Coordinates +// ------------------------------------------------------------------------------------ + +/** \brief Set up a perspective projection matrix + * + * \param m A 4x4 Matrix + * \param fovy_degrees Field of View in degrees + * \param aspect Aspect ratio that determines the field of view in the x direction. + * \param nearVal Distance from the viewer to the near clipping plane (always positive) + * \param farVal Distance from the viewer to the far clipping plane (always positive) + * + */ +void nema_mat4x4_load_perspective(nema_matrix4x4_t m, float fovy_degrees, float aspect, + float nearVal, float farVal); + + +/** \brief Set up a Right Hand perspective projection matrix + * + * \param m A 4x4 Matrix + * \param fovy_degrees Field of View in degrees + * \param aspect Aspect ratio that determines the field of view in the x direction. + * \param nearVal Distance from the viewer to the near clipping plane (always positive) + * \param farVal Distance from the viewer to the far clipping plane (always positive) + * + */ +void nema_mat4x4_load_perspective_rh(nema_matrix4x4_t m, float fovy_degrees, float aspect, + float nearVal, float farVal); + +/** \brief Set up an orthographic projection matrix + * + * \param m A 4x4 Matrix + * \param left Left vertical clipping plane + * \param right Right vertical clipping plane + * \param bottom bottom horizontal clipping plane + * \param top Top horizontal clipping plane + * \param nearVal Distance from the viewer to the near clipping plane (always positive) + * \param farVal Distance from the viewer to the far clipping plane (always positive) + * + */ +void nema_mat4x4_load_ortho(nema_matrix4x4_t m, + float left, float right, + float bottom, float top, + float nearVal, float farVal); + +/** \brief Set up a 2D orthographic projection matrix + * + * \param m A 4x4 Matrix + * \param left Left vertical clipping plane + * \param right Right vertical clipping plane + * \param bottom bottom horizontal clipping plane + * \param top Top horizontal clipping plane + * + */ +void nema_mat4x4_load_ortho_2d(nema_matrix4x4_t m, + float left, float right, + float bottom, float top); + +/** \brief Set up a Right Hand view matrix. + * + * \param m A 4x4 Matrix + * \param eye_x Eye position x. + * \param eye_y Eye position y. + * \param eye_z Eye position z. + * \param center_x Center x to look at + * \param center_y Center y to look at + * \param center_z Center z to look at + * \param up_x Up vector x. (Usually 0) + * \param up_y Up vector y. (Usually 1) + * \param up_z Up vector z. (Usually 0) + * + */ +void nema_mat4x4_look_at_rh(nema_matrix4x4_t m, + float eye_x, float eye_y, float eye_z, + float center_x, float center_y, float center_z, + float up_x, float up_y, float up_z); + +// ------------------------------------------------------------------------------------ +// Clip Coordinates to Window Coordinates +// ------------------------------------------------------------------------------------ + +/** \brief Convenience Function to calculate window coordinates from object coordinates + * + * \param mvp Model, View and Projection Matrix + * \param x_orig Window top left X coordinate + * \param y_orig Window top left Y coordinate + * \param width Window width + * \param height Window height + * \param nearVal Distance from the viewer to the near clipping plane (always positive) + * \param farVal Distance from the viewer to the far clipping plane (always positive) + * \param x X object coordinate + * \param y Y object coordinate + * \param z Z object coordinate + * \param w W object coordinate + * \return 1 if vertex is outside frustum (should be clipped) + * + */ +int nema_mat4x4_obj_to_win_coords(nema_matrix4x4_t mvp, + float x_orig, float y_orig, + int width, int height, + float nearVal, float farVal, + float *x, + float *y, + float *z, + float *w); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libs/nema_gfx/include/nema_provisional.h b/libs/nema_gfx/include/nema_provisional.h new file mode 100644 index 000000000..0ad05f331 --- /dev/null +++ b/libs/nema_gfx/include/nema_provisional.h @@ -0,0 +1,124 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + + +#ifndef NEMA_PROVISIONAL_H__ +#define NEMA_PROVISIONAL_H__ + +#include "nema_sys_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \brief Fill a triangle strip with color (float coordinates) + * + * \param vertices pointer to vertices coordinated (first x coordinate of vertex, + * then y coordinate of vertex) + * \param num_vertices number of vertices + * \param stride Distance between two vertices + * \param rgba8888 Color to be used + * + */ +void nema_fill_triangle_strip_f(float* vertices, int num_vertices, int stride, uint32_t rgba8888); + +/** \brief Fill a traingle fan with color (float coordinates) + * + * \param vertices pointer to vertices coordinated (first x coordinate of vertex, + * then y coordinate of vertex) + * \param num_vertices number of vertices + * \param stride Distance between two vertices + * \param rgba8888 Color to be used + * + */ +void nema_fill_triangle_fan_f(float* vertices, int num_vertices, int stride, uint32_t rgba8888); + +/** \brief Draws a triangle with specific border width. Apply AA if available. + * Degenerated triangles have undefined behavior. + * + * \param x0 x coordinate at the first vertex of the triangle + * \param y0 y coordinate at the first vertex of the triangle + * \param x1 x coordinate at the second vertex of the triangle + * \param y1 y coordinate at the second vertex of the triangle + * \param x2 x coordinate at the third vertex of the triangle + * \param y2 y coordinate at the third vertex of the triangle + * \param border_width triangle's border width + * \param color color of the triangle + * + */ +void nema_draw_triangle_aa(float x0, float y0, float x1, float y1, float x2, float y2, + float border_width, uint32_t color); + + +/** \brief Draw a colored rectangle with rounded edges and specific border width. Apply AA if available. + * + * \param x x coordinate of the upper left vertex of the rectangle + * \param y y coordinate at the upper left vertex of the rectangle + * \param w width of the rectangle + * \param h height of the rectangle + * \param r corner radius + * \param border_width border width + * \param rgba8888 rgba color of the rounded rectangle + * + */ +void nema_draw_rounded_rect_aa(float x, float y, float w, float h, float r, float border_width, uint32_t rgba8888); + + +/** \brief Draw a filled colored rectangle with rounded edges and specific border width. Apply AA if available. + * + * \param x x coordinate of the upper left vertex of the rectangle + * \param y y coordinate at the upper left vertex of the rectangle + * \param w width of the rectangle + * \param h height of the rectangle + * \param r corner radius + * \param rgba8888 rgba color of the rounded rectangle + * + */ +void nema_fill_rounded_rect_aa(float x, float y, float w, float h, float r, uint32_t rgba8888); + +/** \brief Draws a quadrilateral with specific border width. Apply AA if available. + * Only Convex quadrilaterals are supported. + * + * \param x0 x coordinate at the first vertex of the quadrilateral + * \param y0 y coordinate at the first vertex of the quadrilateral + * \param x1 x coordinate at the second vertex of the quadrilateral + * \param y1 y coordinate at the second vertex of the quadrilateral + * \param x2 x coordinate at the third vertex of the quadrilateral + * \param y2 y coordinate at the third vertex of the quadrilateral + * \param x3 x coordinate at the fourth vertex of the quadrilateral + * \param y3 y coordinate at the fourth vertex of the quadrilateral + * \param border_width trianquadrilateralgle's border width + * \param color color of the quadrilateral + * + */ +void nema_draw_quad_aa(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, + float border_width, uint32_t color); +#ifdef __cplusplus +} +#endif + +#endif // NEMA_PROVISIONAL_H__ diff --git a/libs/nema_gfx/include/nema_raster.h b/libs/nema_gfx/include/nema_raster.h new file mode 100644 index 000000000..c8cfa2f0a --- /dev/null +++ b/libs/nema_gfx/include/nema_raster.h @@ -0,0 +1,107 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + + +#ifndef NEMA_RASTER_H__ +#define NEMA_RASTER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \private */ +void nema_set_raster_color(uint32_t rgba8888); + +/** \private */ +void nema_raster_pixel(int x, int y); + +/** \private */ +void nema_raster_line(int x0, int y0, int x1, int y1); + +/** \private */ +void nema_raster_triangle_fx(int x0fx, int y0fx, int x1fx, int y1fx, int x2fx, int y2fx); + + +/** \private */ +void nema_raster_rect(int x, int y, int w, int h); + +/** \private */ +void nema_raster_rounded_rect(int x0, int y0, int w, int h, int r); + + +/** \private */ +void nema_raster_quad_fx(int x0fx, int y0fx, + int x1fx, int y1fx, int x2fx, int y2fx, int x3fx, int y3fx); + +/** \private */ +void nema_raster_triangle (int x0, int y0, int x1, int y1, int x2, int y2); + +/** \private */ +void nema_raster_quad (int x0,int y0,int x1,int y1,int x2,int y2,int x3,int y3); + +/** \private */ +void nema_raster_circle_aa(float x, float y, float r); + +/** \private */ +void nema_raster_stroked_circle_aa(float x, float y, float r, float w); + +/** \private */ +void nema_raster_rect_fx(int xfx, int yfx, int wfx, int hfx); + +/** \private */ +void nema_raster_rect_f(float x, float y, float w, float h); + +/** \private */ +void +nema_raster_triangle_f(float x0, float y0, float x1, float y1, float x2, float y2); + +/** \private */ +void +nema_raster_triangle_p0_f(float x0, float y0); + +/** \private */ +void +nema_raster_triangle_p1_f(float x1, float y1); + +/** \private */ +void +nema_raster_triangle_p2_f(float x2, float y2); + +/** \private */ +void +nema_raster_quad_f(float x0, float y0, float x1, float y1, + float x2, float y2, float x3, float y3); + +/** \private */ +void +nema_raster_stroked_arc_aa( float x0, float y0, float r, float w, float start_angle, float end_angle); + +#ifdef __cplusplus +} +#endif + +#endif //NEMA_RASTER_H__ diff --git a/libs/nema_gfx/include/nema_sys_defs.h b/libs/nema_gfx/include/nema_sys_defs.h new file mode 100644 index 000000000..17174fbcd --- /dev/null +++ b/libs/nema_gfx/include/nema_sys_defs.h @@ -0,0 +1,58 @@ +/** + ****************************************************************************** + * @file nema_sys_defs.h + * @author MCD Application Team + * @brief Header file of NemaGFX System Definitions for STM32 Platforms. + * This file provides definition of types being used by the NemaGFX + * library. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef NEMA_SYS_DEFS_H__ +#define NEMA_SYS_DEFS_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Includes ------------------------------------------------------------------*/ +#include +#include +#include +#include + +/* Temporarily added by ST */ +#ifdef __ICCARM__ +#define FORCE_INLINE _Pragma("inline = forced") +#else +#define FORCE_INLINE +#endif + +/* No Multi-Thread support */ +#define TLS_VAR + +#ifdef NEMA_VG_INVALIDATE_CACHE +void platform_disable_cache(void); +void platform_invalidate_cache(void); + +#define NEMA_VG_DISABLE_CACHE platform_disable_cache() +#define NEMA_VG_ENABLE_INVALIDATE_CACHE platform_invalidate_cache() +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* NEMA_SYS_DEFS_H__ */ diff --git a/libs/nema_gfx/include/nema_transitions.h b/libs/nema_gfx/include/nema_transitions.h new file mode 100644 index 000000000..c8fd3f254 --- /dev/null +++ b/libs/nema_gfx/include/nema_transitions.h @@ -0,0 +1,210 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + + +#ifndef NEMA_TRANSITIONS_H__ +#define NEMA_TRANSITIONS_H__ + +#include "nema_blender.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + NEMA_TRANS_LINEAR_H, + NEMA_TRANS_CUBE_H, + NEMA_TRANS_INNERCUBE_H, + NEMA_TRANS_STACK_H, + NEMA_TRANS_LINEAR_V, + NEMA_TRANS_CUBE_V, + NEMA_TRANS_INNERCUBE_V, + NEMA_TRANS_STACK_V, + NEMA_TRANS_FADE, + NEMA_TRANS_FADE_ZOOM, + NEMA_TRANS_MAX, + NEMA_TRANS_NONE, +} nema_transition_t; + +/** \brief Transition from 'initial' texture to 'final' texture. The transition is complete when 'step' is 0 or 1 + * + * \param effect Transition effect + * \param initial Initial texture + * \param final Final texture + * \param blending_mode Blending mode + * \param step Transition step within [0.f , 1.f] range + * \param width Texture width + * \param height Texture height + * + */ +void nema_transition(nema_transition_t effect, nema_tex_t initial, nema_tex_t final, + uint32_t blending_mode, float step, int width, int height); + + +/** \brief Linear transition horizontally. When 'step' changes from zero to one, textures move from right to left, +otherwise textures move from left to right. The transition is complete when 'step' is 0 or 1. + * + * \param left Texture on the left side + * \param right Texture on the right side + * \param blending_mode Blending mode + * \param step Current step within [0.f , 1.f] range + * \param width Texture width + * + */ +void nema_transition_linear_hor(nema_tex_t left, nema_tex_t right, + uint32_t blending_mode, float step, int width); + +/** \brief Linear transition vertically. When 'step' changes from zero to one, textures move from top to bottom, +otherwise textures move from bottom to top. The transition is complete when 'step' is 0 or 1. + * + * \param up Texture on the top side + * \param down Texture on the bottom side + * \param blending_mode Blending mode + * \param step Current step within [0.f , 1.f] range + * \param height Texture height + * + */ +void nema_transition_linear_ver(nema_tex_t up, nema_tex_t down, + uint32_t blending_mode, float step, int height); + +/** \brief Cubic (textures are mapped on the external faces of a cube) transition horizontally. When 'step' changes from zero to one, textures move from left to right, +otherwise textures move from right to left. The transition is complete when 'step' is 0 or 1. + * + * \param left Texture on the left side + * \param right Texture on the right side + * \param blending_mode Blending mode + * \param step Current step within [0.f , 1.f] range + * \param width Texture width + * \param height Texture height + * + */ +void nema_transition_cube_hor(nema_tex_t left, nema_tex_t right, + uint32_t blending_mode, float step, int width, int height); + +/** \brief Cube (textures are mapped on the external faces of a cube) transition vertically. When 'step' changes from zero to one, textures move from top to bottom, +otherwise textures move from bottom to top. The transition is complete when 'step' is 0 or 1. + * + * \param up Texture on the top side + * \param down Texture on the bottom side + * \param blending_mode Blending mode + * \param step Current step within [0.f , 1.f] range + * \param width Texture width + * \param height Texture height + * + */ +void nema_transition_cube_ver(nema_tex_t up, nema_tex_t down, + uint32_t blending_mode, float step, int width, int height); + +/** \brief Inner Cube (textures are mapped on the internal faces of a cube) transition horizontally. When 'step' changes from zero to one, textures move from left to right, +otherwise textures move from right to left. The transition is complete when 'step' is 0 or 1. + * + * \param left Texture on the left side + * \param right Texture on the right side + * \param blending_mode Blending mode + * \param step Current step within [0.f , 1.f] range + * \param width Texture width + * \param height Texture height + * + */ +void nema_transition_innercube_hor(nema_tex_t left, nema_tex_t right, + uint32_t blending_mode, float step, int width, int height); + +/** \brief Inner Cube (textures are mapped on the internal faces of a cube) transition vertically. When 'step' changes from zero to one, textures move from top to bottom, +otherwise textures move from bottom to top. The transition The transition is complete when 'step' is 0 or 1. + * + * \param up Texture on the top side + * \param down Texture on the bottom side + * \param blending_mode Blending mode + * \param step Current step within [0.f , 1.f] range + * \param width Texture width + * \param height Texture height + * + */ +void nema_transition_innercube_ver(nema_tex_t up, nema_tex_t down, + uint32_t blending_mode, float step, int width, int height); + +/** \brief Stack transition horizontally. When 'step' changes from zero to one, textures move from left to right, +otherwise textures move from right to left. The transition is complete when 'step' is 0 or 1. + * + * \param up Texture on the top side + * \param down Texture on the bottom side + * \param blending_mode Blending mode + * \param step Current step within [0.f , 1.f] range + * \param width Texture width + * \param height Texture height + * + */ +void nema_transition_stack_hor(nema_tex_t left, nema_tex_t right, float step, + int width, int height); + +/** \brief Stack transition vertically. When 'step' moves from zero to one, textures move from top to bottom, +otherwise textures move from bottom to top. The transition is complete when 'step' is 0 or 1. + * + * \param up Texture on the top side + * \param down Texture on the bottom side + * \param blending_mode Blending mode + * \param step Current step within [0.f , 1.f] range + * \param width Texture width + * \param height Texture height + * + */ +void nema_transition_stack_ver(nema_tex_t up, nema_tex_t down, float step, + int width, int height); + +/** \brief Fade transition. Initial texture is being faded out, while final texture is being faded in. +The transition is complete when 'step' is 0 or 1. + * + * \param left Texture on the left side + * \param right Texture on the right side + * \param blending_mode Blending mode + * \param step Current step within [0.f , 1.f] range + * \param width Texture width + * \param height Texture height + * + */ +void nema_transition_fade(nema_tex_t initial, nema_tex_t final, + uint32_t blending_mode, float step, int width, int height); + +/** \brief Fade-zoom transition. Initial texture is being zoomed and faded out, while final texture is being zoomed and faded in. +The transition is complete when 'step' is 0 or 1. + * + * \param initial Initial texture + * \param final Final texture + * \param blending_mode Blending mode + * \param step Current step within [0.f , 1.f] range + * \param width Texture width + * \param height Texture height + * + */ +void nema_transition_fade_zoom(nema_tex_t initial, nema_tex_t final, + uint32_t blending_mode, float step, int width, int height); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libs/nema_gfx/include/nema_utils.h b/libs/nema_gfx/include/nema_utils.h new file mode 100644 index 000000000..0bff05a91 --- /dev/null +++ b/libs/nema_gfx/include/nema_utils.h @@ -0,0 +1,50 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + + +#ifndef NEMA_UTILS_H_ +#define NEMA_UTILS_H_ + +#include "nema_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +float nema_get_time(void); +float nema_get_wall_time(void); +nema_buffer_t nema_load_file(const char *filename, int length, void *buffer); +int nema_save_file(const char *filename, int length, void *buffer); +unsigned int nema_rand(void); +void nema_calculate_fps(void); +void * nema_memcpy ( void * destination, const void * source, size_t num ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libs/nema_gfx/include/nema_vg.h b/libs/nema_gfx/include/nema_vg.h new file mode 100644 index 000000000..068559f3e --- /dev/null +++ b/libs/nema_gfx/include/nema_vg.h @@ -0,0 +1,218 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + +/** + * @file + * @brief Core NemaVG API drawing and initialization functions. + * + */ + +#ifndef __NEMA_VG_H__ +#define __NEMA_VG_H__ + +#include "nema_core.h" +#include "nema_sys_defs.h" +#include "nema_vg_path.h" +#include "nema_vg_paint.h" +#include "nema_vg_context.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// ------------------------------------------------------------------------------- +// SETUP +// ------------------------------------------------------------------------------- + +/** \brief Initializes NemaVG library and allocates the stencil buffer to the default memory pool (NEMA_MEM_POOL_FB) + * Call either this or nema_vg_init_stencil_pool to allocate the stencil buffer to a different memory pool + * or nema_vg_init_stencil_prealloc to provide the stencil buffer + * \param width Framebuffer width + * \param height Framebuffer height + */ +void nema_vg_init(int width, int height); + +/** \brief Initializes NemaVG library and allocate the stencil buffer in a specific memory pool. + * Call either this or nema_vg_init to allocate the stencil buffer to the default memory pool (NEMA_MEM_POOL_FB) + * or nema_vg_init_stencil_prealloc to provide the stencil buffer + * \param width Framebuffer width + * \param height Framebuffer height + * \param pool Memory pool for allocating the stencil buffer (memory pools are platform specific and defined in nema_sys_defs.h file) + */ +void nema_vg_init_stencil_pool(int width, int height, int pool); + +/** \brief Initializes NemaVG library without allocating the stencil buffer which is provided by the user. + * Call either this or nema_vg_init to allocate the stencil buffer to the default memory pool (NEMA_MEM_POOL_FB) + * or nema_vg_init_stencil_pool to allocate the stencil buffer to a different memory pool + * \param width Framebuffer width + * \param height Framebuffer height + * \param stencil_bo stencil buffer + */ +void nema_vg_init_stencil_prealloc(int width, int height, nema_buffer_t stencil_bo); + + +/** \brief Reinitialize NemaVG library after a gpu powerofff + * + */ +void nema_vg_reinit(); + +/** \brief Deinitialize NemaVG library. Free memory from implicitly allocated objects (stencil buffer + * if created inside the library, lut buffer and tsvgs' path, paint and gradient buffers) + * + * + */ +void nema_vg_deinit(); + +// ------------------------------------------------------------------------------- +// PATH DRAW +// ------------------------------------------------------------------------------- + +/** \brief Draw a path using a specified paint object + * + * \param path Pointer (handle) to the path that will be drawn + * \param paint Pointer (handle) to the paint object that wil be used for drawing + + * \return Error code. See NEMA_VG_ERR_* defines in "nema_vg_context.h" header file for the error codes. + * + */ +uint32_t nema_vg_draw_path(NEMA_VG_PATH_HANDLE path, NEMA_VG_PAINT_HANDLE paint); + +/** \brief Draw a line shape + * + * \param x1 Upper left x coordinate + * \param y1 Upper left y coordinate + * \param x2 The width + * \param y2 The height + * \param m 3x3 affine transformation matrix + * \param paint The paint to draw + + * \return Error code. See NEMA_VG_ERR_* defines in "nema_vg_context.h" header file for the error codes. + * + */ +uint32_t nema_vg_draw_line(float x1, float y1, float x2, float y2, + nema_matrix3x3_t m, + NEMA_VG_PAINT_HANDLE paint); + +/** \brief Draw a rectangle shape + * + * \param x Upper left x coordinate + * \param y Upper left y coordinate + * \param width The width + * \param height The height + * \param m 3x3 affine transformation matrix + * \param paint The paint to draw + + * \return Error code + * + */ +uint32_t nema_vg_draw_rect(float x, float y, float width, float height, + nema_matrix3x3_t m, + NEMA_VG_PAINT_HANDLE paint); + +/** \brief Draw a rounded rectangle shape + * + * \param x Upper left x coordinate + * \param y Upper left y coordinate + * \param width The width + * \param height The height + * \param rx Horizontal cornel radius + * \param ry Vertical cornel radius + * \param m 3x3 affine transformation matrix + * \param paint The paint to draw + + * \return Error code. See NEMA_VG_ERR_* defines in "nema_vg_context.h" header file for the error codes. + * + */ +uint32_t nema_vg_draw_rounded_rect(float x, float y, float width, float height, + float rx, float ry, + nema_matrix3x3_t m, + NEMA_VG_PAINT_HANDLE paint); + +/** \brief Draw a ellipse shape + * + * \param cx The x position of the ellipse + * \param cy The y position of the ellipse + * \param rx Radius on the x axis + * \param ry Radius on the y axis + * \param m 3x3 affine transformation matrix + * \param paint The paint to draw + + * \return Error code. See NEMA_VG_ERR_* defines in "nema_vg_context.h" header file for the error codes. + * + */ +uint32_t nema_vg_draw_ellipse(float cx, float cy, float rx, float ry, + nema_matrix3x3_t m, + NEMA_VG_PAINT_HANDLE paint); + +/** \brief Draw a circle shape + * + * \param cx The x center of the circle + * \param cy The y center of the circle + * \param r Radius of the circle + * \param m 3x3 affine transformation matrix + * \param paint The paint to draw + + * \return Error code. See NEMA_VG_ERR_* defines in "nema_vg_context.h" header file for the error codes. + * + */ +uint32_t nema_vg_draw_circle(float cx, float cy, float r, + nema_matrix3x3_t m, + NEMA_VG_PAINT_HANDLE paint); + + +/** \brief Draw a filled ring with rounded caps shape. In case of a conical gradient paint type, + * the conical gradient center should be at the center of the ring(cx, cy). In other case, where the two centers do not match, + * the ring should be drawn with NEMA_VG_QUALITY_MAXIMUM. The ring width can be set with the paint's stroke_width. + * + * \param cx The center x coordinate of the ring + * \param cy The center y coordinate of the ring + * \param ring_radius The radius of the ring + * \param angle_start The angle in degrees of the ring + * \param angle_end The angle in degrees that ends this ring + * \param paint The paint to draw + + * \return Error code. See NEMA_VG_ERR_* defines in "nema_vg_context.h" header file for the error codes. + * + */ +uint32_t nema_vg_draw_ring(float cx, float cy, float ring_radius, float angle_start, float angle_end, + NEMA_VG_PAINT_HANDLE paint); + + +/** \brief Returns the minimum and maximum values for the coordinates that + * can be handled by the underlying hardware + * + * \param min_coord Minimum coordinate (x or y) value (pointer) + * \param max_coord Maximum coordinate (x or y) value (pointer) + * + */ +void nema_vg_get_coord_limits(float *min_coord, float *max_coord); + +#ifdef __cplusplus +} +#endif + +#endif //__NEMA_VG_H__ diff --git a/libs/nema_gfx/include/nema_vg_context.h b/libs/nema_gfx/include/nema_vg_context.h new file mode 100644 index 000000000..9f4fee794 --- /dev/null +++ b/libs/nema_gfx/include/nema_vg_context.h @@ -0,0 +1,187 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + +/** + * @file + * @brief NemaVG Context interface. + * + * Contains NemaVG error codes, fill rules, rendering quality defines and functions for updating various rendering parameters. + * The functions defined here can be used to access the context parameters. The Context is an internal (opaque) struct of NemaVG. + */ + +#ifndef __NEMA_VG_CONTEXT_H__ +#define __NEMA_VG_CONTEXT_H__ + +#include "nema_graphics.h" +#include "nema_matrix3x3.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifndef NEMA_VG_HANDLE +#define NEMA_VG_HANDLE void* /**< NemaVG handle object (void pointer)*/ +#endif + +#define NEMA_VG_PATH_HANDLE NEMA_VG_HANDLE /**< NemaVG path handle (pointer to path object)*/ +#define NEMA_VG_PAINT_HANDLE NEMA_VG_HANDLE /**< NemaVG paint handle (pointer to paint object)*/ +#define NEMA_VG_GRAD_HANDLE NEMA_VG_HANDLE /**< NemaVG gradient handle (pointer to gradient object)*/ + +typedef float nema_vg_float_t; /**< Floating point data type (default is 'float') */ + +#define NEMA_VG_ERR_NO_ERROR (0x00000000U) /**< No Error */ +#define NEMA_VG_ERR_BAD_HANDLE (0x00000001U) /**< Bad handle */ +#define NEMA_VG_ERR_BAD_BUFFER (0x00000002U) /**< Bad buffer */ +#define NEMA_VG_ERR_INVALID_FILL_RULE (0x00000004U) /**< Invalid fill rule*/ +#define NEMA_VG_ERR_INVALID_PAINT_TYPE (0x00000008U) /**< Invalid paint type*/ +#define NEMA_VG_ERR_INVALID_VERTEX_DATA (0x00000010U) /**< Invalid vertex data*/ +#define NEMA_VG_ERR_NO_RADIAL_ENABLED (0x00000020U) /**< Radial not present in HW*/ +#define NEMA_VG_ERR_NO_BOUND_CL (0x00000040U) /**< No bound CL*/ +#define NEMA_VG_ERR_INVALID_ARGUMENTS (0x00000080U) /**< Invalid arguments*/ +#define NEMA_VG_ERR_INVALID_ARC_DATA (0x00000100U) /**< reserved */ +#define NEMA_VG_ERR_CL_FULL (0x00000200U) /**< reserved */ +#define NEMA_VG_ERR_DRAW_OUT_OF_BOUNDS (0x00000400U) /**< Path is out of the drawing area */ +#define NEMA_VG_ERR_INVALID_MASKING_OBJ (0x00000800U) /**< Masking object was not set */ +#define NEMA_VG_ERR_INVALID_MASKING_FORMAT (0x00001000U) /**< Invalid Masking object Format */ +#define NEMA_VG_ERR_INVALID_LUT_IDX_FORMAT (0x00002000U) /**< Invalid LUT indices object Format */ +#define NEMA_VG_ERR_COORDS_OUT_OF_RANGE (0x00004000U) /**< Path coordinates out of supported range */ +#define NEMA_VG_ERR_EMPTY_TSVG (0x00008000U) /**< Tsvg has no geometries */ +#define NEMA_VG_ERR_NO_BOUND_FONT (0x00010000U) /**< There is no bound font */ +#define NEMA_VG_ERR_UNSUPPORTED_FONT (0x00020000U) /**< The font is not supported (eg. older version) by NemaVG API */ +#define NEMA_VG_ERR_NON_INVERTIBLE_MATRIX (0x00040000U) /**< A matrix that needs to be inverted, is not invertible */ +#define NEMA_VG_ERR_INVALID_GRAD_STOPS (0x00080000U) /**< Gradient stops exceed maximum available stops */ +#define NEMA_VG_ERR_NO_INIT (0x00100000U) /**< VG uninitialized */ +#define NEMA_VG_ERR_INVALID_STROKE_WIDTH (0x00200000U) /**< Invalid stroke width */ +#define NEMA_VG_ERR_INVALID_OPACITY (0x00400000U) /**< Invalid opacity */ + +#define NEMA_VG_FILL_DRAW (0x00U) /**< DEPRECATED Stroke fill rule */ +#define NEMA_VG_STROKE (0x00U) /**< Stroke fill rule */ +#define NEMA_VG_FILL_EVEN_ODD (0x01U) /**< Evenodd fill rule */ +#define NEMA_VG_FILL_NON_ZERO (0x02U) /**< Non zero fill rule */ + +#define NEMA_VG_QUALITY_BETTER (0x00U) /**< Better rendering quality (default option, balances rendering quality and performance)*/ +#define NEMA_VG_QUALITY_FASTER (0x01U) /**< Faster rendering quality (favors performance over rendering quality)*/ +#define NEMA_VG_QUALITY_MAXIMUM (0x02U) /**< Maximum rendering quality (favors rendering quality over performance)*/ +#define NEMA_VG_QUALITY_NON_AA (0x10U) /**< Rendering quality without AA*/ + + +/** \brief Set the global transformation matrix. Global matrix will be applied in all NemaVG rendering operations that will follow. + * + * \param m transformation matrix + * + * \return Error code + */ +uint32_t nema_vg_set_global_matrix(nema_matrix3x3_t m); + + +/** \brief Disable the global transformation matrix. + * + */ +void nema_vg_reset_global_matrix(void); + +/** \brief Set the fill rule that will be applied when rendering a path. + * + * \param fill_rule fill rule (NEMA_VG_STROKE, NEMA_VG_FILL_EVEN_ODD, NEMA_VG_FILL_NON_ZERO) + * + */ +void nema_vg_set_fill_rule(uint8_t fill_rule); + +/** \brief Enable/Disable Masking. + * + * \param masking 1 to enable, 0 to disable + * + */ +void nema_vg_masking(uint8_t masking); + +/** \brief Set the mask object (texture) + * + * \param mask_obj Texture to be used as mask. Its format must be NEMA_A1, NEMA_A2, NEMA_A4 or Nema_A8, otherwise it will return an error. + * \return Error code. If no error occurs, NEMA_VG_ERR_NO_ERROR otherwise NEMA_VG_ERR_INVALID_MASKING_FORMAT. + * + */ +uint32_t nema_vg_set_mask(nema_img_obj_t *mask_obj); + +/** \brief Translate the mask object (texture) with respect to origin point (0, 0). Sets the position of the mask object. + * + * \param x Horizontal position to place the mask object + * \param y Horizontal position to place the mask object + * + */ +void nema_vg_set_mask_translation(float x, float y); + +/** \brief Set the rendering quality + * + * \param quality level (NEMA_VG_QUALITY_BETTER, NEMA_VG_QUALITY_FASTER, NEMA_VG_QUALITY_MAXIMUM, NEMA_VG_QUALITY_NON_AA) + * + */ +void nema_vg_set_quality(uint8_t quality); + +/** \brief Set the blending mode for VG operations (see nema_blender.h documentation in NemaGFX API Manual) + * Additional Blending Operations: only NEMA_BLOP_SRC_PREMULT is supported + * + * \param blend Blending mode + * \see nema_blending_mode() + * + */ +void nema_vg_set_blend(uint32_t blend); + +/** \brief Get the current error code. Clears the error afterwards. + * + * \return Error code. See NEMA_VG_ERR_* defines for all the possible error codes. + */ +uint32_t nema_vg_get_error(void); + +/** \brief Enable/disable large coordinates handling when rendering a TSVG, a path or a predefined shape + * + * \param enable 0 to disable, 1 to enable + * \param allow_internal_alloc 0 to not allow internal allocation, 1 to allow + * + */ +void nema_vg_handle_large_coords(uint8_t enable, uint8_t allow_internal_alloc); + +/** \brief Bind segment and data buffers to be used for handling large coordinates + * + * \param segs Pointer to segment buffer for large coordinates + * \param segs_size_bytes Segment buffer size in bytes + * \param data Pointer to data buffer for large coordinates + * \param data_size_bytes Data buffer size in bytes + * + */ +uint32_t nema_vg_bind_clip_coords_buf(void *segs, uint32_t segs_size_bytes, void *data, uint32_t data_size_bytes); + +/** \brief Unbind segment and data buffers to be used for handling large coordinates + * + * + */ +void nema_vg_unbind_clip_coords_buf(void); + +#ifdef __cplusplus +} +#endif + +#endif //__NEMA_VG_CONTEXT_H__ diff --git a/libs/nema_gfx/include/nema_vg_font.h b/libs/nema_gfx/include/nema_vg_font.h new file mode 100644 index 000000000..8739a7c03 --- /dev/null +++ b/libs/nema_gfx/include/nema_vg_font.h @@ -0,0 +1,184 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + +/** + * @file + * @brief Vector font rendering + * + * This file includes the necessary structs and functions that are used for rendering text (strings and single characters), + * using vector fonts. The accompanying vector font converter utility, converts truetype fonts (ttf files) to instances + * of the structs defined here. A use case of this module is included in the respective examples (examples/NemaVG/render_vg_font). + */ + +#ifndef NEMA_VG_FONT_H_ +#define NEMA_VG_FONT_H_ + +#include "nema_matrix3x3.h" +#include "nema_vg.h" +#include "nema_vg_context.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NEMA_VG_ALIGNX_LEFT (0x00U) /**< Align horizontally to the left */ +#define NEMA_VG_ALIGNX_RIGHT (0x01U) /**< Align horizontally to the right */ +#define NEMA_VG_ALIGNX_CENTER (0x02U) /**< Align horizontally centered */ +#define NEMA_VG_ALIGNX_JUSTIFY (0x03U) /**< Justify horizontally */ +#define NEMA_VG_ALIGNX_MASK (0x03U) /**< Horizontal alignment mask */ +#define NEMA_VG_ALIGNY_TOP (0x00U) /**< Align vertically to the top */ +#define NEMA_VG_ALIGNY_BOTTOM (0x04U) /**< Align vertically to the bottom */ +#define NEMA_VG_ALIGNY_CENTER (0x08U) /**< Align vertically centered */ +#define NEMA_VG_ALIGNY_JUSTIFY (0x0cU) /**< Justify vertically */ +#define NEMA_VG_ALIGNY_MASK (0x0cU) /**< Vertical alignment mask */ +#define NEMA_VG_TEXT_WRAP (0x10U) /**< Use text wrapping */ + +#define NEMA_VG_CHAR_LTR (0x00U) /**< Character follows left to right orientation */ +#define NEMA_VG_CHAR_RTL (0x01U) /**< Character follows right to left orientation */ +#define NEMA_VG_CHAR_TTB (0x00U) /**< Character follows top to bottom orientation */ +#define NEMA_VG_CHAR_BTT (0x02U) /**< Character follows bottom to top orientation */ + + +/** NemaVG Kerning pair information data struct */ +typedef struct { + const uint32_t left; /**< Neighbor character to the left of the current one (Unicode value) */ + const float x_offset; /**< Kerning offset value (horizontally) */ +} nema_vg_kern_pair_t; + +/** NemaVG data struct of a glyph in vector format*/ +typedef struct { + const uint32_t data_offset; /**< Offset value for the data of the glyph in the respective data array */ + const size_t data_length; /**< Length of the data in the respective data array */ + const uint32_t segment_offset; /**< Offset value for the segments of the glyph in the respective segment array */ + const size_t segment_length; /**< Length of the segments in the respective segment array */ + const float xAdvance; /**< Advance width*/ + const uint32_t kern_offset; /**< Kerning offset of the glyph in the respective kerning array */ + const uint8_t kern_length; /**< Length of the kerning information of the glyph */ + const int16_t bbox_xmin; /**< Minimum x of the glyph's bounding box */ + const int16_t bbox_ymin; /**< Minimum y of the glyph's bounding box */ + const int16_t bbox_xmax; /**< Maximum x of the glyph's bounding box */ + const int16_t bbox_ymax; /**< Maximum y of the glyph's bounding box */ +} nema_vg_glyph_t; + +/** NemaVG vector font range data struct */ +typedef struct { + const uint32_t first; /**< Unicode value of the first value of the range */ + const uint32_t last; /**< Unicode value of the last value of the range */ + const nema_vg_glyph_t *glyphs; /**< Pointer to the array of glyphs */ +} nema_vg_font_range_t; + +/** NemaVG vector font data struct*/ +typedef struct { + const uint32_t version; /**< Font version */ + const nema_vg_font_range_t *ranges; /**< Pointer to the array of ranges */ + const nema_vg_float_t *data; /**< Pointer to the data of the vector font */ + const size_t data_length; /**< Length of the vector font data*/ + const uint8_t *segment; /**< Pointer to the segments of the vector font */ + const size_t segment_length; /**< Length of the vector font segments */ + const float size; /**< Default font size (height) */ + const float xAdvance; /**< Default advance width. If the space character is included in the ranges, then its advance width is set */ + const float ascender; /**< Vertical distance from the baseline to the highest point of the font */ + const float descender; /**< Vertical distance from the baseline to the lowest point of the font */ + const nema_vg_kern_pair_t *kern_pairs; /**< Pointer to the array of the font's kerning pairs */ + uint32_t flags; /**< Bit field, reserved for future use */ +} nema_vg_font_t; + +/** \brief Bind the font to use in future nema_vg_print() calls. Sets error code if font is not supported. + * + * \param font Pointer to the vector font + * + */ +void nema_vg_bind_font(nema_vg_font_t *font); + +/** \brief Sets the size of the bound font. Future nema_vg_print() and nema_vg_print_char() calls will print using the last set size. + * + * \param font Pointer to the vector font + * + */ +void nema_vg_set_font_size(float size); + + +/** \brief Print pre-formatted text + * + * \param paint Pointer to the current paint object (contains the text color) + * \param str Pointer to string + * \param x X coordinate of text-area's top-left corner + * \param y Y coordinate of text-area's top-left corner + * \param w Max allowed width + * \param h Max allowed height + * \param align Alignment and wrapping mode + * \param m Transformation matrix + * + */ +void nema_vg_print(NEMA_VG_PAINT_HANDLE paint, const char *str, float x, float y, float w, float h, uint32_t align, nema_matrix3x3_t m); + + +/** \brief Get the bounding box's width and height of a vector string. Prior to calling this function, "nema_vg_set_font_size" must be called first. + * + * \param str Pointer to string + * \param w Pointer to variable where width should be written + * \param h Pointer to variable where height should be written + * \param max_w Max allowed width + * \param size font size + * \param wrap enable text wraping + * \return Number of carriage returns + * + */ +int nema_vg_string_get_bbox(const char *str, float *w, float *h, float max_w, uint32_t wrap); + + +/** \brief Get the text ascender value in point units. Font size must be set pror to calling this function. + * + * \return Ascender pt + * + */ +int nema_vg_get_ascender_pt(); + +/** \brief Print a single character + * + * \details The position of the character is determined by the 'orientation' argument. + * x and y arguments define a point on the baseline. If the orientation is left to right (LTR), + * the character will be placed to the right of the (x, y) point. Right to left (RTL) will place + * the character to the left of the (x, y) point. Top to bottom (TTB) will have the same effect as + * RTL and bottom to top (BTT) will place the character higher than the (x, y) point by an offset + * equal to the font height. + * + * \param paint Pointer to the current paint object (contains the text color) + * \param ch Character to be printed + * \param x X coordinate of character's top-left or top-right corner (controlled by the 'orientation' parameter) + * \param y Y coordinate of character's top-left or bottom-left corner (controlled by the 'orientation' parameter) + * \param m Transformation matrix + * \param orientation Character orientation (see NEMA_VG_CHAR_* defines) + * \return Character width in pixels + * + */ +float nema_vg_print_char(NEMA_VG_PAINT_HANDLE paint, char ch, float x, float y, nema_matrix3x3_t m, uint32_t orientation); + +#ifdef __cplusplus +} +#endif +#endif // NEMA_VG_FONT_H_ diff --git a/libs/nema_gfx/include/nema_vg_paint.h b/libs/nema_gfx/include/nema_vg_paint.h new file mode 100644 index 000000000..76f16bbbe --- /dev/null +++ b/libs/nema_gfx/include/nema_vg_paint.h @@ -0,0 +1,241 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + +/** + * @file + * @brief Paint operation related fuctions. Paint is an internal (opaque) struct of NemaVG. + * The functions defined here can be used access its parameters. + * + */ + +#ifndef __NEMA_VG_PAINT_H__ +#define __NEMA_VG_PAINT_H__ + +#include "nema_interpolators.h" +#include "nema_matrix3x3.h" +#include "nema_vg_context.h" +#include "nema_graphics.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NEMA_VG_PAINT_COLOR (0x00U) /**< Fill with color */ +#define NEMA_VG_PAINT_FILL (0x00U) /**< Deprecated - Fill with color (same as NEMA_VG_PAINT_COLOR) */ +#define NEMA_VG_PAINT_GRAD_LINEAR (0x01U) /**< Fill with linear gradient */ +#define NEMA_VG_PAINT_TEXTURE (0x02U) /**< Fill with texture */ +#define NEMA_VG_PAINT_GRAD_RADIAL (0x03U) /**< Fill with radial gradient */ +#define NEMA_VG_PAINT_GRAD_CONICAL (0x04U) /**< Fill with conical gradient */ + +#define NEMA_VG_PAINT_MAX_GRAD_STOPS (32) /**< Maximum gradient stops*/ + +/** \brief Create a paint object. + * + * \return Handle to the created paint object + * + */ +NEMA_VG_PAINT_HANDLE nema_vg_paint_create(); + +/** \brief Destroy a paint object. + * + * \param paint Handle to paint object that should be destroyed + * + */ +void nema_vg_paint_destroy(NEMA_VG_PAINT_HANDLE paint); + +/** \brief Clear the parameters of a paint object. + * + * \param paint Pointer (handle) to paint object + * + */ +void nema_vg_paint_clear(NEMA_VG_PAINT_HANDLE paint); + +/** \brief Set the paint type + * + * \param paint Pointer (handle) to paint + * \param type Paint type (NEMA_VG_PAINT_COLOR, NEMA_VG_PAINT_GRAD_LINEAR, NEMA_VG_PAINT_TEXTURE, NEMA_VG_PAINT_GRAD_RADIAL, NEMA_VG_PAINT_GRAD_CONICAL) + * + */ +void nema_vg_paint_set_type(NEMA_VG_PAINT_HANDLE paint, uint8_t type); + + +/** \brief Lock paint transformation to path. If locked, path and paint + * transformation will be in sync. + * + * \param paint Pointer to paint object + * \param locked 1 if locked (default), 0 if not locked + * + */ +void nema_vg_paint_lock_tran_to_path(NEMA_VG_PAINT_HANDLE paint, int locked); + +/** \brief Set linear gradient to a paint object + * + * \param paint Pointer to paint object + * \param grad Pointer to gradient object + * \param x0 Linear gradient start point x coordinate + * \param y0 Linear gradient start point y coordinate + * \param x1 Linear gradient end point x coordinate + * \param y1 Linear gradient end point y coordinate + * \param sampling_mode Sampling mode. NEMA_TEX_BORDER defaults to NEMA_TEX_CLAMP + * + */ +void nema_vg_paint_set_grad_linear(NEMA_VG_PAINT_HANDLE paint, + NEMA_VG_GRAD_HANDLE grad, + float x0, float y0, + float x1, float y1, + nema_tex_mode_t sampling_mode); + + /** \brief Set the paint color + * + * \param paint Pointer (handle) to paint object + * \param rgba Color to be set, in rgba (hex 0xAABBGGRR) format + * + */ +void nema_vg_paint_set_paint_color(NEMA_VG_PAINT_HANDLE paint, uint32_t rgba); + + /** \brief Set the paint opacity + * + * \param paint Pointer (pointer) to paint object + * \param opacity Opacity to be set, 1 is fully opaque and 0 is fully transparent + * + */ +void nema_vg_paint_set_opacity(NEMA_VG_PAINT_HANDLE paint, float opacity); + + /** \brief Set stroke width + * + * \param paint Pointer (handle) to paint object + * \param stroke_width Stroke width to be set + * + */ +void nema_vg_paint_set_stroke_width(NEMA_VG_PAINT_HANDLE paint, float stroke_width); + + /** \brief Set transformation matrix for texture + * + * \param paint Pointer (handle) to paint object + * \param m 3x3 transformation matrix + * + */ +void nema_vg_paint_set_tex_matrix(NEMA_VG_PAINT_HANDLE paint, nema_matrix3x3_t m); + + /** \brief Set texture to paint object + * + * \param paint Pointer (handle) to paint + * \param text Pointer to texture image object + * + */ +void nema_vg_paint_set_tex(NEMA_VG_PAINT_HANDLE paint, nema_img_obj_t* tex); + + /** \brief Set Lut-based (look-up-table) texture to paint object. See Nema Pixpresso User Manual regarding Lut formats + * + * \param paint Pointer (handle) to paint object + * \param lut_palette Pointer to the Palette of the Lut image object + * \param lut_indices Pointer to the indices of the Lut image object + * + */ +void nema_vg_paint_set_lut_tex(NEMA_VG_PAINT_HANDLE paint, nema_img_obj_t* lut_palette, nema_img_obj_t* lut_indices); + +/** \brief Set Conical gradient to paint object + * + * \param paint Pointer (handle) to paint + * \param grad Pointer (handle) to gradient + * \param cx Conical gradient center point x coordinate + * \param cy Conical gradient center point y coordinate + * \param sampling_mode Sampling mode + * + */ +void nema_vg_paint_set_grad_conical(NEMA_VG_PAINT_HANDLE paint, + NEMA_VG_GRAD_HANDLE grad, + float cx, float cy, + nema_tex_mode_t sampling_mode); + +/** \brief Set radial gradient to paint object + * + * \param paint Pointer (handle) to paint + * \param grad Pointer (handle) to gradient + * \param x0 Radial gradient center point x coordinate + * \param y0 Radial gradient center point y coordinate + * \param r Radial gradient radius + * \param sampling_mode Sampling mode + * + */ +void +nema_vg_paint_set_grad_radial(NEMA_VG_PAINT_HANDLE paint, + NEMA_VG_GRAD_HANDLE grad, + float x0, float y0, + float r, + nema_tex_mode_t sampling_mode); + + +/** \brief Set radial gradient to paint object, with different horizontal and vertical radius + * + * \param paint Pointer (handle) to paint + * \param grad Pointer (handle) to gradient + * \param x0 Radial gradient center point x coordinate + * \param y0 Radial gradient center point y coordinate + * \param rx Radial gradient radius on x axis + * \param ry Radial gradient radius on y axis + * \param sampling_mode Sampling mode + * + */ +void +nema_vg_paint_set_grad_radial2(NEMA_VG_PAINT_HANDLE paint, + NEMA_VG_GRAD_HANDLE grad, + float x0, float y0, + float rx, float ry, + nema_tex_mode_t sampling_mode); + +/** \brief Create gradient object + * + * \return Handle (pointer) to the created gradient object + */ +NEMA_VG_GRAD_HANDLE +nema_vg_grad_create(void); + +/** \brief Destroy gradient object + * + * \param grad Pointer to the gradient object + * + */ +void +nema_vg_grad_destroy(NEMA_VG_GRAD_HANDLE grad); + +/** \brief Set gradient parameters to a gradient object + * + * \param grad Pointer (handle) to gradient object + * \param stops_count Number of stop colors + * \param stops Pointer to stop colors coordinates + * \param colors Pointer to stop color values + * + */ +void +nema_vg_grad_set(NEMA_VG_GRAD_HANDLE grad, int stops_count, float *stops, color_var_t* colors); + +#ifdef __cplusplus +} +#endif + +#endif //__NEMA_VG_PAINT_H__ diff --git a/libs/nema_gfx/include/nema_vg_path.h b/libs/nema_gfx/include/nema_vg_path.h new file mode 100644 index 000000000..6a799c0a1 --- /dev/null +++ b/libs/nema_gfx/include/nema_vg_path.h @@ -0,0 +1,143 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + +/** + * @file + * @brief Path operation related fuctions + * + */ + +#ifndef __NEMA_VG_PATH_H__ +#define __NEMA_VG_PATH_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#include "nema_interpolators.h" +#include "nema_matrix3x3.h" +#include "nema_sys_defs.h" +#include "nema_vg_context.h" + +#define NEMA_VG_PRIM_CLOSE (0x00U) /**< Close segment */ +#define NEMA_VG_PRIM_MOVE (0x01U) /**< Move segment */ +#define NEMA_VG_PRIM_LINE (0x02U) /**< Line segment */ +#define NEMA_VG_PRIM_HLINE (0x03U) /**< Horizontal line segment */ +#define NEMA_VG_PRIM_VLINE (0x04U) /**< Vertical line segment */ +#define NEMA_VG_PRIM_BEZIER_QUAD (0x05U) /**< Quadratic bezier segment */ +#define NEMA_VG_PRIM_BEZIER_CUBIC (0x06U) /**< Cubic bezier segment */ +#define NEMA_VG_PRIM_BEZIER_SQUAD (0x07U) /**< Smooth quadratic bezier segment */ +#define NEMA_VG_PRIM_BEZIER_SCUBIC (0x08U) /**< Smooth cubic bezier segment */ +#define NEMA_VG_PRIM_ARC (0x09U) /**< Arc segment */ +#define NEMA_VG_PRIM_POLYGON (0x0AU) /**< Polygon segment */ +#define NEMA_VG_PRIM_POLYLINE (0x0BU) /**< Polyline segment */ +#define NEMA_VG_PRIM_MASK (0x0FU) /**< Mask for all segments */ +#define NEMA_VG_REL (0x10U) /**< Rel segment*/ +#define NEMA_VG_ARC_LARGE (0x20U) /**< Large arc segment */ +#define NEMA_VG_ARC_CW (0x40U) /**< Clockwise arc segment */ +#define NEMA_VG_PRIM_SCCWARC (NEMA_VG_PRIM_ARC ) /**< Small counterclockwise arc segment */ +#define NEMA_VG_PRIM_SCWARC (NEMA_VG_PRIM_ARC | NEMA_VG_ARC_CW ) /**< Small clockwise arc segment */ +#define NEMA_VG_PRIM_LCCWARC (NEMA_VG_PRIM_ARC | NEMA_VG_ARC_LARGE) /**< Large counterclockwise arc segment */ +#define NEMA_VG_PRIM_LCWARC (NEMA_VG_PRIM_ARC | NEMA_VG_ARC_CW |NEMA_VG_ARC_LARGE) /**< Large clockwise arc segment */ +#define NEMA_VG_PRIM_MOVE_REL (NEMA_VG_PRIM_MOVE | NEMA_VG_REL) /**< Relative move segment */ +#define NEMA_VG_PRIM_LINE_REL (NEMA_VG_PRIM_LINE | NEMA_VG_REL) /**< Relative line segment */ +#define NEMA_VG_PRIM_HLINE_REL (NEMA_VG_PRIM_HLINE | NEMA_VG_REL) /**< Relative horizontal line segment */ +#define NEMA_VG_PRIM_VLINE_REL (NEMA_VG_PRIM_VLINE | NEMA_VG_REL) /**< Relative vertical line segment */ +#define NEMA_VG_PRIM_BEZIER_QUAD_REL (NEMA_VG_PRIM_BEZIER_QUAD | NEMA_VG_REL) /**< Relative quadratic bezier segment */ +#define NEMA_VG_PRIM_BEZIER_CUBIC_REL (NEMA_VG_PRIM_BEZIER_CUBIC | NEMA_VG_REL) /**< Relative cubic bezier segment */ +#define NEMA_VG_PRIM_BEZIER_SQUAD_REL (NEMA_VG_PRIM_BEZIER_SQUAD | NEMA_VG_REL) /**< Relative smooth quadratic bezier segment */ +#define NEMA_VG_PRIM_BEZIER_SCUBIC_REL (NEMA_VG_PRIM_BEZIER_SCUBIC | NEMA_VG_REL) /**< Relative smooth cubic bezier segment */ +#define NEMA_VG_PRIM_SCCWARC_REL (NEMA_VG_PRIM_SCCWARC | NEMA_VG_REL) /**< Relative small counterclockwise arc segment */ +#define NEMA_VG_PRIM_SCWARC_REL (NEMA_VG_PRIM_SCWARC | NEMA_VG_REL) /**< Relative small clockwise arc segment */ +#define NEMA_VG_PRIM_LCCWARC_REL (NEMA_VG_PRIM_LCCWARC | NEMA_VG_REL) /**< Relative lareg counterclockwise arc segment */ +#define NEMA_VG_PRIM_LCWARC_REL (NEMA_VG_PRIM_LCWARC | NEMA_VG_REL) /**< Relative lareg rclockwise arc segment */ +#define NEMA_VG_PRIM_POLYGON_REL (NEMA_VG_PRIM_POLYGON | NEMA_VG_REL) /**< Relative polygon segment */ +#define NEMA_VG_PRIM_POLYLINE_REL (NEMA_VG_PRIM_POLYLINE | NEMA_VG_REL) /**< Relative polyline segment */ + + +/** \brief Create path + * + * \return Created path + * + */ +NEMA_VG_PATH_HANDLE nema_vg_path_create(); + +/** \brief Destroy path + * + * \param path Pointer to Path + * \return void + * + */ +void nema_vg_path_destroy(NEMA_VG_PATH_HANDLE path); + +/** \brief Clear path + * + * \param path Pointer to Path + * \return void + * + */ +void nema_vg_path_clear(NEMA_VG_PATH_HANDLE path); + +/** \brief Set path shape (vertex buffer) + * + * \param path Pointer to path + * \param seg_size Number of segments to be added + * \param seg Pointer to segments + * \param data_size Number of data to be added + * \param data Pointer to coordinates + * + */ +void nema_vg_path_set_shape(NEMA_VG_PATH_HANDLE path, const size_t seg_size , const uint8_t* seg, const size_t data_size, const nema_vg_float_t* data); + +/** \brief Set path shape (vertex buffer) and bounding box. Same functionality as nema_vg_path_set_shape() + * but bbox is given by user (reduces CPU utilization) + * + * \param path Pointer to path + * \param seg_size Number of segments to be added + * \param seg Pointer to segments + * \param data_size Number of data to be added + * \param data Pointer to coordinates + * \param bbox Pointer to shape bound box coordinates {min_x, min_y, max_x, max_y} + * + */ +void +nema_vg_path_set_shape_and_bbox(NEMA_VG_PATH_HANDLE path, const size_t seg_size, const uint8_t* seg, const size_t data_size, const nema_vg_float_t* data, const nema_vg_float_t *bbox); + +/** \brief Set affine transformation matrix + * + * \param path Pointer to path + * \param m 3x3 affine transformation matrix + * + */ +void nema_vg_path_set_matrix(NEMA_VG_PATH_HANDLE path, nema_matrix3x3_t m); + +#ifdef __cplusplus +} +#endif + +#endif //__NEMA_VG_PATH_H__ diff --git a/libs/nema_gfx/include/nema_vg_tsvg.h b/libs/nema_gfx/include/nema_vg_tsvg.h new file mode 100644 index 000000000..ca9b4ac35 --- /dev/null +++ b/libs/nema_gfx/include/nema_vg_tsvg.h @@ -0,0 +1,56 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + +/** + * @file + * @brief API for rendering .tsvg images + * + */ + +#ifndef NEMA_VG_TSVG_H_ +#define NEMA_VG_TSVG_H_ + +#include "nema_vg_context.h" + +/** \brief Draws a TSVG buffer + * + * \param buffer Pointer to the TSVG buffer that will be drawn + * + */ +void +nema_vg_draw_tsvg(const void* buffer); + +/** \brief Get the width and height of tsvg + * + * \param buffer Tsvg buffer + * \param width return Tsvg width + * \param height return Tsvg height + * + */ +void nema_vg_get_tsvg_resolution(const void *buffer, uint32_t *width, uint32_t *height); + +#endif // NEMA_VG_TSVG_H_ diff --git a/libs/nema_gfx/include/nema_vg_version.h b/libs/nema_gfx/include/nema_vg_version.h new file mode 100644 index 000000000..f14c42648 --- /dev/null +++ b/libs/nema_gfx/include/nema_vg_version.h @@ -0,0 +1,55 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + +/** + * @file + * @brief Contains version numbers for NemaVG API and the currently supported font version. + * + */ + +#ifndef NEMA_VG_VERSION_H__ +#define NEMA_VG_VERSION_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define NEMA_VG_MAJOR_VERSION 0x01U /**< NemaVG API version, major number */ +#define NEMA_VG_MINOR_VERSION 0x01U /**< NemaVG API version, minor number */ +#define NEMA_VG_REVISION_VERSION 0x05U /**< NemaVG API version, revision number */ +#define NEMA_VG_IMP_VERSION 0x00231000U /**< NemaVG API version, implementation in format 0x00YYMM00 (Y: year, M: month) */ + +#define NEMA_VG_API_VERSION ((NEMA_VG_MAJOR_VERSION << 16) + (NEMA_VG_MINOR_VERSION << 8) + (NEMA_VG_REVISION_VERSION)) /**< NemaVG API version in format 0x00MMmmrr (M:major, m:minor, r:revision if any) */ + +#define NEMA_VG_FONT_VERSION 0x01U /**< Current font version */ + + +#ifdef __cplusplus +} +#endif + +#endif //NEMA_VG_VERSION_H__ diff --git a/libs/nema_gfx/include/tsi_malloc.h b/libs/nema_gfx/include/tsi_malloc.h new file mode 100644 index 000000000..902b765d9 --- /dev/null +++ b/libs/nema_gfx/include/tsi_malloc.h @@ -0,0 +1,64 @@ +/* TSI 2023.xmo */ +/******************************************************************************* + * Copyright (c) 2023 Think Silicon Single Member PC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this header file and/or associated documentation files to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Materials, and to permit persons to whom the Materials are furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS + * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX + * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT: + * https://think-silicon.com/products/software/nemagfx-api + * + * The software is provided 'as is', without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall + * Think Silicon Single Member PC be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising + * from, out of or in connection with the software or the use or other dealings + * in the software. + ******************************************************************************/ + +#ifndef TSI_MALLOC_H__ +#define TSI_MALLOC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#define tsi_malloc_init(base_virt, base_phys, size, reset) \ + tsi_malloc_init_pool(0, base_virt, base_phys, size, reset) + +#define tsi_malloc(size) tsi_malloc_pool(0, size) + +int tsi_malloc_init_pool( int pool, + void *base_virt, + uintptr_t base_phys, + int size, + int reset); + +int tsi_malloc_init_pool_aligned( int pool, + void *base_virt, + uintptr_t base_phys, + int size, + int reset, + int alignment); /*alignment must be multiple of 4, otherwise it will be overwritten internaly to be multiple of 4*/ + +void *tsi_malloc_pool(int pool, int size); +void tsi_free(void *ptr); +uintptr_t tsi_virt2phys(void *addr); +void *tsi_phys2virt(uintptr_t addr); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libs/nema_gfx/lib/core/cortex_m33/gcc/libnemagfx-float-abi-hard-wc16.a b/libs/nema_gfx/lib/core/cortex_m33/gcc/libnemagfx-float-abi-hard-wc16.a new file mode 100644 index 000000000..3408727b5 Binary files /dev/null and b/libs/nema_gfx/lib/core/cortex_m33/gcc/libnemagfx-float-abi-hard-wc16.a differ diff --git a/libs/nema_gfx/lib/core/cortex_m33/gcc/libnemagfx-float-abi-hard.a b/libs/nema_gfx/lib/core/cortex_m33/gcc/libnemagfx-float-abi-hard.a new file mode 100644 index 000000000..a6a5bf688 Binary files /dev/null and b/libs/nema_gfx/lib/core/cortex_m33/gcc/libnemagfx-float-abi-hard.a differ diff --git a/libs/nema_gfx/lib/core/cortex_m33/gcc/libnemagfx-wc16.a b/libs/nema_gfx/lib/core/cortex_m33/gcc/libnemagfx-wc16.a new file mode 100644 index 000000000..65557188b Binary files /dev/null and b/libs/nema_gfx/lib/core/cortex_m33/gcc/libnemagfx-wc16.a differ diff --git a/libs/nema_gfx/lib/core/cortex_m33/gcc/libnemagfx.a b/libs/nema_gfx/lib/core/cortex_m33/gcc/libnemagfx.a new file mode 100644 index 000000000..39f62f4f2 Binary files /dev/null and b/libs/nema_gfx/lib/core/cortex_m33/gcc/libnemagfx.a differ diff --git a/lv_conf_template.h b/lv_conf_template.h index 03ed16485..1df77b528 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -206,6 +206,22 @@ #define LV_USE_DRAW_SW_COMPLEX_GRADIENTS 0 #endif +/*Use TSi's aka (Think Silicon) NemaGFX */ +#define LV_USE_NEMA_GFX 0 + +#if LV_USE_NEMA_GFX + #define LV_NEMA_GFX_HAL_INCLUDE + + /*Enable Vector Graphics Operations. Available only if NemaVG library is present*/ + #define LV_USE_NEMA_VG 0 + + #if LV_USE_NEMA_VG + /*Define application's resolution used for VG related buffer allocation */ + #define LV_NEMA_GFX_MAX_RESX 800 + #define LV_NEMA_GFX_MAX_RESY 600 + #endif +#endif + /** Use NXP's VG-Lite GPU on iMX RTxxx platforms. */ #define LV_USE_DRAW_VGLITE 0 diff --git a/src/draw/nema_gfx/lv_draw_nema_gfx.c b/src/draw/nema_gfx/lv_draw_nema_gfx.c new file mode 100644 index 000000000..f6f2bac0c --- /dev/null +++ b/src/draw/nema_gfx/lv_draw_nema_gfx.c @@ -0,0 +1,382 @@ +/** + * MIT License + * + * ----------------------------------------------------------------------------- + * Copyright (c) 2008-24 Think Silicon Single Member PC + * ----------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** + * @file lv_draw_nema_gfx.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../../core/lv_refr.h" + +#if LV_USE_NEMA_GFX + +#include "lv_draw_nema_gfx.h" +#include "../../font/lv_font.h" +#include "../../font/lv_font_fmt_txt.h" + +/********************* + * DEFINES + *********************/ + +#define DRAW_UNIT_ID_NEMA_GFX 7 + +/********************** + * TYPEDEFS + **********************/ + +#if LV_USE_OS +/** + * Structure of pending nema_gfx draw task + */ +typedef struct _nema_gfx_draw_task_t { + lv_draw_task_t * task; + bool flushed; +} nema_gfx_draw_task_t; +#endif + +/********************** + * STATIC PROTOTYPES + **********************/ + +#if LV_USE_OS + static void nema_gfx_render_thread_cb(void * ptr); +#endif + +static void nema_gfx_execute_drawing(lv_draw_nema_gfx_unit_t * u); + +static int32_t nema_gfx_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer); + +static int32_t nema_gfx_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task); + +static int32_t nema_gfx_delete(lv_draw_unit_t * draw_unit); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_nema_gfx_init(void) +{ + lv_draw_nema_gfx_unit_t * draw_nema_gfx_unit = lv_draw_create_unit(sizeof(lv_draw_nema_gfx_unit_t)); + /*Initiallize NemaGFX*/ + nema_init(); +#if LV_USE_NEMA_VG + /*Initiallize NemaVG */ + nema_vg_init(LV_NEMA_GFX_MAX_RESX, LV_NEMA_GFX_MAX_RESY); + /* Allocate VG Buffers*/ + draw_nema_gfx_unit->paint = nema_vg_paint_create(); + draw_nema_gfx_unit->gradient = nema_vg_grad_create(); + draw_nema_gfx_unit->path = nema_vg_path_create(); +#endif + draw_nema_gfx_unit->base_unit.dispatch_cb = nema_gfx_dispatch; + draw_nema_gfx_unit->base_unit.evaluate_cb = nema_gfx_evaluate; + draw_nema_gfx_unit->base_unit.delete_cb = nema_gfx_delete; + /*Create GPU Command List*/ + draw_nema_gfx_unit->cl = nema_cl_create(); + /*Bind Command List*/ + nema_cl_bind_circular(&(draw_nema_gfx_unit->cl)); + + +#if LV_USE_OS + lv_thread_init(&draw_nema_gfx_unit->thread, LV_THREAD_PRIO_HIGH, nema_gfx_render_thread_cb, 2 * 1024, + draw_nema_gfx_unit); +#endif +} + +void lv_draw_nema_gfx_deinit(void) +{ + return; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static int32_t nema_gfx_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task) +{ + lv_draw_nema_gfx_unit_t * draw_nema_gfx_unit = (lv_draw_nema_gfx_unit_t *)draw_unit; + + switch(task->type) { + case LV_DRAW_TASK_TYPE_LAYER: { + if(task->preference_score > 80) { + task->preference_score = 80; + task->preferred_draw_unit_id = DRAW_UNIT_ID_NEMA_GFX; + } + return 1; + } +#if LV_USE_NEMA_VG + case LV_DRAW_TASK_TYPE_TRIANGLE: + case LV_DRAW_TASK_TYPE_ARC: { + lv_draw_arc_dsc_t * draw_arc_dsc = (lv_draw_arc_dsc_t *) task->draw_dsc; + if(draw_arc_dsc->rounded == 0) break; + } + case LV_DRAW_TASK_TYPE_FILL: { + if(task->preference_score > 80) { + task->preference_score = 80; + task->preferred_draw_unit_id = DRAW_UNIT_ID_NEMA_GFX; + } + return 1; + } +#else + case LV_DRAW_TASK_TYPE_FILL: { + lv_draw_fill_dsc_t * draw_fill_dsc = (lv_draw_fill_dsc_t *) task->draw_dsc; + if((draw_fill_dsc->grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_NONE)) { + if(task->preference_score > 80) { + task->preference_score = 80; + task->preferred_draw_unit_id = DRAW_UNIT_ID_NEMA_GFX; + } + return 1; + } + break; + } + case LV_DRAW_TASK_TYPE_TRIANGLE: { + lv_draw_triangle_dsc_t * draw_triangle_dsc = (lv_draw_triangle_dsc_t *) task->draw_dsc; + if((draw_triangle_dsc->bg_grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_NONE)) { + if(task->preference_score > 80) { + task->preference_score = 80; + task->preferred_draw_unit_id = DRAW_UNIT_ID_NEMA_GFX; + } + return 1; + } + break; + } +#endif + case LV_DRAW_TASK_TYPE_IMAGE: { + lv_draw_image_dsc_t * draw_image_dsc = (lv_draw_image_dsc_t *) task->draw_dsc; + if(draw_image_dsc->blend_mode == LV_BLEND_MODE_NORMAL || draw_image_dsc->blend_mode == LV_BLEND_MODE_ADDITIVE) { + if(task->preference_score > 80) { + task->preference_score = 80; + task->preferred_draw_unit_id = DRAW_UNIT_ID_NEMA_GFX; + } + return 1; + } + break; + } + case LV_DRAW_TASK_TYPE_LABEL: { + lv_draw_label_dsc_t * draw_label_dsc = (lv_draw_label_dsc_t *) task->draw_dsc; + lv_font_fmt_txt_dsc_t * fdsc = (lv_font_fmt_txt_dsc_t *)(draw_label_dsc->font->dsc); + if(fdsc->bitmap_format != LV_FONT_FMT_TXT_COMPRESSED) { + if(task->preference_score > 80) { + task->preference_score = 80; + task->preferred_draw_unit_id = DRAW_UNIT_ID_NEMA_GFX; + } + return 1; + } + break; + } + case LV_DRAW_TASK_TYPE_LINE: { + lv_draw_line_dsc_t * draw_line_dsc = (lv_draw_line_dsc_t *) task->draw_dsc; + bool is_dashed = (draw_line_dsc->dash_width && draw_line_dsc->dash_gap); + if(!is_dashed && !(draw_line_dsc->round_end || draw_line_dsc->round_start)) { + if(task->preference_score > 80) { + task->preference_score = 80; + task->preferred_draw_unit_id = DRAW_UNIT_ID_NEMA_GFX; + } + return 1; + } + break; + } + case LV_DRAW_TASK_TYPE_BORDER: { + const lv_draw_border_dsc_t * draw_dsc = (lv_draw_border_dsc_t *) task->draw_dsc; + if((!(draw_dsc->side != (lv_border_side_t)LV_BORDER_SIDE_FULL && draw_dsc->radius > 0)) && + (draw_dsc->radius > draw_dsc->width)) { + if(task->preference_score > 80) { + task->preference_score = 80; + task->preferred_draw_unit_id = DRAW_UNIT_ID_NEMA_GFX; + } + return 1; + } + break; + } + case LV_DRAW_TASK_TYPE_BOX_SHADOW: + case LV_DRAW_TASK_TYPE_MASK_RECTANGLE: + case LV_DRAW_TASK_TYPE_MASK_BITMAP: + case LV_DRAW_TASK_TYPE_VECTOR: + default: + break; + } + nema_cl_wait(&(draw_nema_gfx_unit->cl)); + return 0; +} + +static int32_t nema_gfx_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer) +{ + lv_draw_nema_gfx_unit_t * draw_nema_gfx_unit = (lv_draw_nema_gfx_unit_t *) draw_unit; + + /* Return immediately if it's busy with draw task. */ + if(draw_nema_gfx_unit->task_act) + return 0; + + /* Try to get an ready to draw. */ + lv_draw_task_t * t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_NEMA_GFX); + + /* Return 0 is no selection, some tasks can be supported by other units. */ + if(t == NULL || t->preferred_draw_unit_id != DRAW_UNIT_ID_NEMA_GFX) + return 0; + + void * buf = lv_draw_layer_alloc_buf(layer); + if(buf == NULL) + return -1; + + t->state = LV_DRAW_TASK_STATE_IN_PROGRESS; + draw_nema_gfx_unit->base_unit.target_layer = layer; + draw_nema_gfx_unit->base_unit.clip_area = &t->clip_area; + draw_nema_gfx_unit->task_act = t; + +#if LV_USE_OS + /* Let the render thread work. */ + if(draw_nema_gfx_unit->inited) + lv_thread_sync_signal(&draw_nema_gfx_unit->sync); +#else + nema_gfx_execute_drawing(draw_nema_gfx_unit); + + draw_nema_gfx_unit->task_act->state = LV_DRAW_TASK_STATE_READY; + draw_nema_gfx_unit->task_act = NULL; + + /* The draw unit is free now. Request a new dispatching as it can get a new task. */ + lv_draw_dispatch_request(); +#endif + + return 1; +} + +static void nema_gfx_execute_drawing(lv_draw_nema_gfx_unit_t * u) +{ + lv_draw_task_t * t = u->task_act; + lv_draw_unit_t * draw_unit = (lv_draw_unit_t *)u; + + switch(t->type) { + case LV_DRAW_TASK_TYPE_FILL: + lv_draw_nema_gfx_fill(draw_unit, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_IMAGE: + lv_draw_nema_gfx_img(draw_unit, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_TRIANGLE: + lv_draw_nema_gfx_triangle(draw_unit, t->draw_dsc); + break; + case LV_DRAW_TASK_TYPE_LABEL: + lv_draw_nema_gfx_label(draw_unit, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_LAYER: + lv_draw_nema_gfx_layer(draw_unit, t->draw_dsc, &t->area); + break; + case LV_DRAW_TASK_TYPE_LINE: + lv_draw_nema_gfx_line(draw_unit, t->draw_dsc); + break; +#if LV_USE_NEMA_VG + case LV_DRAW_TASK_TYPE_ARC: + lv_draw_nema_gfx_arc(draw_unit, t->draw_dsc, &t->area); + break; +#endif + case LV_DRAW_TASK_TYPE_BORDER: + lv_draw_nema_gfx_border(draw_unit, t->draw_dsc, &t->area); + break; + default: + break; + } +} + +static int32_t nema_gfx_delete(lv_draw_unit_t * draw_unit) +{ +#if LV_USE_NEMA_VG + /*Free VG Buffers*/ + lv_draw_nema_gfx_unit_t * draw_nema_gfx_unit = (lv_draw_nema_gfx_unit_t *) draw_unit; + nema_vg_paint_destroy(draw_nema_gfx_unit->paint); + nema_vg_path_destroy(draw_nema_gfx_unit->path); + nema_vg_grad_destroy(draw_nema_gfx_unit->gradient); +#endif + +#if LV_USE_OS + lv_draw_nema_gfx_unit_t * _draw_nema_gfx_unit = (lv_draw_nema_gfx_unit_t *) draw_unit; + LV_LOG_INFO("Cancel NemaGFX draw thread."); + _draw_nema_gfx_unit->exit_status = true; + + if(_draw_nema_gfx_unit->inited) + lv_thread_sync_signal(&_draw_nema_gfx_unit->sync); + + lv_result_t res = lv_thread_delete(&_draw_nema_gfx_unit->thread); + + return res; +#endif + +#if LV_USE_NEMA_VG == 0 && LV_USE_OS == LV_OS_NONE + LV_UNUSED(draw_unit); +#endif + return 0; +} + +#if LV_USE_OS +static void nema_gfx_render_thread_cb(void * ptr) +{ + lv_draw_nema_gfx_unit_t * u = ptr; + + lv_thread_sync_init(&u->sync); + u->inited = true; + + while(1) { + /* Wait for sync if there is no task set. */ + while(u->task_act == NULL) { + if(u->exit_status) + break; + + lv_thread_sync_wait(&u->sync); + } + + if(u->exit_status) { + LV_LOG_INFO("Ready to exit NemaGFX draw thread."); + break; + } + + if(u->task_act) { + nema_gfx_execute_drawing(u); + } + /* Signal the ready state to dispatcher. */ + u->task_act->state = LV_DRAW_TASK_STATE_READY; + /* Cleanup. */ + u->task_act = NULL; + + /* The draw unit is free now. Request a new dispatching as it can get a new task. */ + lv_draw_dispatch_request(); + } + + u->inited = false; + lv_thread_sync_delete(&u->sync); + LV_LOG_INFO("Exit NemaGFX draw thread."); +} +#endif + +#endif diff --git a/src/draw/nema_gfx/lv_draw_nema_gfx.h b/src/draw/nema_gfx/lv_draw_nema_gfx.h new file mode 100644 index 000000000..e455bb77f --- /dev/null +++ b/src/draw/nema_gfx/lv_draw_nema_gfx.h @@ -0,0 +1,122 @@ +/** + * MIT License + * + * ----------------------------------------------------------------------------- + * Copyright (c) 2008-24 Think Silicon Single Member PC + * ----------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** + * @file lv_draw_nema_gfx.h + * + */ + +#ifndef LV_DRAW_NEMA_GFX_H +#define LV_DRAW_NEMA_GFX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../lv_conf_internal.h" + +#if LV_USE_NEMA_GFX + +#include "lv_draw_nema_gfx_utils.h" + +#include "../lv_draw_private.h" +#include "../lv_draw_buf_private.h" +#include "../lv_draw_image_private.h" +#include "../lv_image_decoder_private.h" +#include "../lv_draw_label_private.h" +#include "../lv_draw_mask_private.h" +#include "../lv_draw_rect_private.h" +#include "../lv_draw_triangle_private.h" +#include "../lv_draw_vector_private.h" + +#include "../../misc/lv_area_private.h" + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + lv_draw_unit_t base_unit; + lv_draw_task_t * task_act; +#if LV_USE_OS + lv_thread_sync_t sync; + lv_thread_t thread; + volatile bool inited; + volatile bool exit_status; +#endif + uint32_t idx; + nema_cmdlist_t cl; +#if LV_USE_NEMA_VG + NEMA_VG_PAINT_HANDLE paint; + NEMA_VG_GRAD_HANDLE gradient; + NEMA_VG_PATH_HANDLE path; +#endif +} lv_draw_nema_gfx_unit_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_draw_nema_gfx_init(void); + +void lv_draw_nema_gfx_deinit(void); + +void lv_draw_nema_gfx_fill(lv_draw_unit_t * draw_unit, + const lv_draw_fill_dsc_t * dsc, const lv_area_t * coords); + +void lv_draw_nema_gfx_triangle(lv_draw_unit_t * draw_unit, const lv_draw_triangle_dsc_t * dsc); + +void lv_draw_nema_gfx_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc, + const lv_area_t * coords); + +void lv_draw_nema_gfx_label(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc, + const lv_area_t * coords); + +void lv_draw_nema_gfx_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, + const lv_area_t * coords); + +void lv_draw_nema_gfx_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc); + +void lv_draw_nema_gfx_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc, + const lv_area_t * coords); + +void lv_draw_nema_gfx_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc, + const lv_area_t * coords); + + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_NEMA_GFX*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_NEMA_GFX_H*/ \ No newline at end of file diff --git a/src/draw/nema_gfx/lv_draw_nema_gfx_arc.c b/src/draw/nema_gfx/lv_draw_nema_gfx_arc.c new file mode 100644 index 000000000..9b02f4593 --- /dev/null +++ b/src/draw/nema_gfx/lv_draw_nema_gfx_arc.c @@ -0,0 +1,92 @@ +/** + * MIT License + * + * ----------------------------------------------------------------------------- + * Copyright (c) 2008-24 Think Silicon Single Member PC + * ----------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** + * @file lv_draw_nema_gfx_arc.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_nema_gfx.h" + +#if LV_USE_NEMA_GFX && LV_USE_NEMA_VG + +/********************** + * GLOBAL FUNCTIONS + **********************/ +void lv_draw_nema_gfx_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc, const lv_area_t * coords) +{ + + LV_UNUSED(coords); + + if(dsc->opa <= (lv_opa_t)LV_OPA_MIN) + return; + if(dsc->width == 0) + return; + if(dsc->start_angle == dsc->end_angle) + return; + + lv_draw_nema_gfx_unit_t * draw_nema_gfx_unit = (lv_draw_nema_gfx_unit_t *)draw_unit; + + lv_layer_t * layer = draw_unit->target_layer; + lv_point_t center = {dsc->center.x - layer->buf_area.x1, dsc->center.y - layer->buf_area.y1}; + + lv_area_t clip_area; + lv_area_copy(&clip_area, draw_unit->clip_area); + lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1); + + nema_set_clip(clip_area.x1, clip_area.y1, lv_area_get_width(&clip_area), lv_area_get_height(&clip_area)); + + lv_value_precise_t end_angle = dsc->end_angle; + + if(dsc->start_angle >= dsc->end_angle) + end_angle = dsc->end_angle + 360.f; + + nema_vg_paint_clear(draw_nema_gfx_unit->paint); + nema_vg_paint_set_type(draw_nema_gfx_unit->paint, NEMA_VG_PAINT_COLOR); + lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa); + uint32_t bg_color = nema_rgba(col32.red, col32.green, col32.blue, col32.alpha); + nema_vg_paint_set_paint_color(draw_nema_gfx_unit->paint, bg_color); // green + nema_vg_paint_set_stroke_width(draw_nema_gfx_unit->paint, dsc->width); + nema_vg_set_blend(NEMA_BL_SRC_OVER | NEMA_BLOP_SRC_PREMULT); + + if(dsc->rounded == 1) { + nema_vg_draw_ring(center.x, center.y, (float)dsc->radius - (float)dsc->width * 0.5f, dsc->start_angle, end_angle, + draw_nema_gfx_unit->paint); + } + else { + /* nema_vg_draw_ring_generic(center.x, center.y, (float)dsc->radius - (float)dsc->width * 0.5f, dsc->start_angle, + end_angle, draw_nema_gfx_unit->paint, 0U); */ + } + + nema_cl_submit(&(draw_nema_gfx_unit->cl)); + +} + +#endif + diff --git a/src/draw/nema_gfx/lv_draw_nema_gfx_border.c b/src/draw/nema_gfx/lv_draw_nema_gfx_border.c new file mode 100644 index 000000000..0d9ada422 --- /dev/null +++ b/src/draw/nema_gfx/lv_draw_nema_gfx_border.c @@ -0,0 +1,223 @@ +/** + * MIT License + * + * ----------------------------------------------------------------------------- + * Copyright (c) 2008-24 Think Silicon Single Member PC + * ----------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** + * @file lv_draw_nema_gfx_fill.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_nema_gfx.h" + +#if LV_USE_NEMA_GFX +#include + +/********************** + * GLOBAL FUNCTIONS + **********************/ +void lv_draw_nema_gfx_border(lv_draw_unit_t * draw_unit, const lv_draw_border_dsc_t * dsc, const lv_area_t * coords) +{ + if(dsc->opa <= LV_OPA_MIN) + return; + if(dsc->width == 0) + return; + if(dsc->side == LV_BORDER_SIDE_NONE) + return; + + lv_draw_nema_gfx_unit_t * draw_nema_gfx_unit = (lv_draw_nema_gfx_unit_t *)draw_unit; + + lv_layer_t * layer = draw_unit->target_layer; + lv_area_t inward_coords; + int32_t width = dsc->width; + + /* Move border inwards to align with software rendered border */ + inward_coords.x1 = coords->x1 + ceil(width / 2.0f); + inward_coords.x2 = coords->x2 - floor(width / 2.0f); + inward_coords.y1 = coords->y1 + ceil(width / 2.0f); + inward_coords.y2 = coords->y2 - floor(width / 2.0f); + + lv_area_move(&inward_coords, -layer->buf_area.x1, -layer->buf_area.y1); + + lv_area_t clip_area; + lv_area_copy(&clip_area, draw_unit->clip_area); + lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1); + + nema_set_clip(clip_area.x1, clip_area.y1, lv_area_get_width(&clip_area), lv_area_get_height(&clip_area)); + + lv_area_t clipped_coords; + if(!lv_area_intersect(&clipped_coords, &inward_coords, &clip_area)) + return; /*Fully clipped, nothing to do*/ + + lv_color_format_t dst_cf = layer->draw_buf->header.cf; + uint32_t dst_nema_cf = lv_nemagfx_cf_to_nema(dst_cf); + + nema_bind_dst_tex((uintptr_t)NEMA_VIRT2PHYS(layer->draw_buf->data), lv_area_get_width(&(layer->buf_area)), + lv_area_get_height(&(layer->buf_area)), dst_nema_cf, + lv_area_get_width(&(layer->buf_area))*lv_color_format_get_size(dst_cf)); + + /* Recalculate float Dimensions */ + float x1 = (float)coords->x1 + ((float)width / 2.0f) - (float)layer->buf_area.x1; + float x2 = (float)coords->x2 - ((float)width / 2.0f) - (float)layer->buf_area.x1; + float y1 = (float)coords->y1 + ((float)width / 2.0f) - (float)layer->buf_area.y1; + float y2 = (float)coords->y2 - ((float)width / 2.0f) - (float)layer->buf_area.y1; + float coords_bg_w = x2 - x1 + 1; + float coords_bg_h = y2 - y1 + 1; + int32_t short_side = LV_MIN(coords_bg_w, coords_bg_h); + float radius = (float)LV_MIN(dsc->radius, short_side >> 1); + + lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa); + uint32_t bg_color = nema_rgba(col32.red, col32.green, col32.blue, col32.alpha); + + if(col32.alpha < 255U) { + nema_set_blend_fill(NEMA_BL_SRC_OVER); + bg_color = nema_premultiply_rgba(bg_color); + } + else { + nema_set_blend_fill(NEMA_BL_SRC); + } + + if(radius > 0.0f) { + nema_draw_rounded_rect_aa(x1, y1, coords_bg_w, coords_bg_h, radius, width, bg_color); + } + else { + lv_area_t rect_coords = *coords; + lv_area_move(&rect_coords, -layer->buf_area.x1, -layer->buf_area.y1); + int32_t border_width = lv_area_get_width(&rect_coords); + int32_t border_height = lv_area_get_height(&rect_coords); + + if(dsc->side & LV_BORDER_SIDE_TOP) { + float x = rect_coords.x1 + width; + float y = rect_coords.y1; + float w = border_width - 2 * width; + float h = width; + nema_enable_aa(1, 0, 1, 0); + nema_fill_rect_f(x, y, w, h, bg_color); + } + + if(dsc->side & LV_BORDER_SIDE_BOTTOM) { + float x = rect_coords.x1 + width; + float y = rect_coords.y1 + border_height - width; + float w = border_width - 2 * width; + float h = width; + nema_enable_aa(1, 0, 1, 0); + nema_fill_rect_f(x, y, w, h, bg_color); + } + + if(dsc->side & LV_BORDER_SIDE_LEFT) { + float x = rect_coords.x1; + float y = rect_coords.y1 + width; + float w = width; + float h = border_height - 2 * width; + nema_enable_aa(0, 1, 0, 1); + nema_fill_rect_f(x, y, w, h, bg_color); + } + + if(dsc->side & LV_BORDER_SIDE_RIGHT) { + float x = rect_coords.x1 + border_width - width; + float y = rect_coords.y1 + width; + float w = width; + float h = border_height - 2 * width; + nema_enable_aa(0, 1, 0, 1); + nema_fill_rect_f(x, y, w, h, bg_color); + } + + /*Draw small corner rectangles + Top Left*/ + if(dsc->side & LV_BORDER_SIDE_TOP || dsc->side & LV_BORDER_SIDE_LEFT) { + float x = rect_coords.x1; + float y = rect_coords.y1; + float w = width; + float h = width; + + if(!(dsc->side & LV_BORDER_SIDE_TOP)) + nema_enable_aa(1, 1, 0, 1); + else if(!(dsc->side & LV_BORDER_SIDE_LEFT)) + nema_enable_aa(1, 0, 1, 1); + else + nema_enable_aa(1, 0, 0, 1); + + nema_fill_rect_f(x, y, w, h, bg_color); + } + + /*Top Right*/ + if(dsc->side & LV_BORDER_SIDE_TOP || dsc->side & LV_BORDER_SIDE_RIGHT) { + float x = rect_coords.x1 + border_width - width; + float y = rect_coords.y1; + float w = width; + float h = width; + + if(!(dsc->side & LV_BORDER_SIDE_TOP)) + nema_enable_aa(1, 1, 0, 1); + else if(!(dsc->side & LV_BORDER_SIDE_RIGHT)) + nema_enable_aa(1, 1, 1, 0); + else + nema_enable_aa(1, 1, 0, 0); + + nema_fill_rect_f(x, y, w, h, bg_color); + } + + /*Bottom Right*/ + if(dsc->side & LV_BORDER_SIDE_BOTTOM || dsc->side & LV_BORDER_SIDE_RIGHT) { + float x = rect_coords.x1 + border_width - width; + float y = rect_coords.y1 + border_height - width; + float w = width; + float h = width; + + if(!(dsc->side & LV_BORDER_SIDE_BOTTOM)) + nema_enable_aa(0, 1, 1, 1); + else if(!(dsc->side & LV_BORDER_SIDE_RIGHT)) + nema_enable_aa(1, 1, 1, 0); + else + nema_enable_aa(0, 1, 1, 0); + + nema_fill_rect_f(x, y, w, h, bg_color); + } + + /*Bottom Left*/ + if(dsc->side & LV_BORDER_SIDE_BOTTOM || dsc->side & LV_BORDER_SIDE_LEFT) { + float x = rect_coords.x1; + float y = rect_coords.y1 + border_height - width; + float w = width; + float h = width; + + if(!(dsc->side & LV_BORDER_SIDE_BOTTOM)) + nema_enable_aa(0, 1, 1, 1); + else if(!(dsc->side & LV_BORDER_SIDE_LEFT)) + nema_enable_aa(1, 0, 1, 1); + else + nema_enable_aa(0, 0, 1, 1); + + nema_fill_rect_f(x, y, w, h, bg_color); + } + + } + + nema_cl_submit(&(draw_nema_gfx_unit->cl)); + +} +#endif diff --git a/src/draw/nema_gfx/lv_draw_nema_gfx_fill.c b/src/draw/nema_gfx/lv_draw_nema_gfx_fill.c new file mode 100644 index 000000000..cdd2de12e --- /dev/null +++ b/src/draw/nema_gfx/lv_draw_nema_gfx_fill.c @@ -0,0 +1,146 @@ +/** + * MIT License + * + * ----------------------------------------------------------------------------- + * Copyright (c) 2008-24 Think Silicon Single Member PC + * ----------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** + * @file lv_draw_nema_gfx_fill.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_nema_gfx.h" + +#if LV_USE_NEMA_GFX + +/********************** + * GLOBAL FUNCTIONS + **********************/ +void lv_draw_nema_gfx_fill(lv_draw_unit_t * draw_unit, const lv_draw_fill_dsc_t * dsc, const lv_area_t * coords) +{ + if(dsc->opa <= LV_OPA_MIN) return; + + lv_draw_nema_gfx_unit_t * draw_nema_gfx_unit = (lv_draw_nema_gfx_unit_t *)draw_unit; + + lv_layer_t * layer = draw_unit->target_layer; + lv_area_t rel_coords; + lv_area_copy(&rel_coords, coords); + lv_area_move(&rel_coords, -layer->buf_area.x1, -layer->buf_area.y1); + + lv_area_t rel_clip_area; + lv_area_copy(&rel_clip_area, draw_unit->clip_area); + lv_area_move(&rel_clip_area, -layer->buf_area.x1, -layer->buf_area.y1); + + nema_set_clip(rel_clip_area.x1, rel_clip_area.y1, lv_area_get_width(&rel_clip_area), + lv_area_get_height(&rel_clip_area)); + + lv_area_t clipped_coords; + if(!lv_area_intersect(&clipped_coords, &rel_coords, &rel_clip_area)) + return; /*Fully clipped, nothing to do*/ + + lv_color_format_t dst_cf = layer->draw_buf->header.cf; + uint32_t dst_nema_cf = lv_nemagfx_cf_to_nema(dst_cf); + + nema_bind_dst_tex((uintptr_t)NEMA_VIRT2PHYS(layer->draw_buf->data), lv_area_get_width(&(layer->buf_area)), + lv_area_get_height(&(layer->buf_area)), dst_nema_cf, + lv_area_get_width(&(layer->buf_area))*lv_color_format_get_size(dst_cf)); + + int32_t coords_bg_w = lv_area_get_width(&rel_coords); + int32_t coords_bg_h = lv_area_get_height(&rel_coords); + int32_t short_side = LV_MIN(coords_bg_w, coords_bg_h); + int32_t radius = LV_MIN(dsc->radius, short_side >> 1); + + if((dsc->grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_NONE)) { + + lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa); + uint32_t bg_color = nema_rgba(col32.red, col32.green, col32.blue, col32.alpha); + + if(col32.alpha < 255U) { + nema_set_blend_fill(NEMA_BL_SRC_OVER); + bg_color = nema_premultiply_rgba(bg_color); + } + else { + nema_set_blend_fill(NEMA_BL_SRC); + } + + if(radius > 0.f) + nema_fill_rounded_rect_aa(rel_coords.x1, rel_coords.y1, coords_bg_w, coords_bg_h, radius, bg_color); + else + nema_fill_rect(rel_coords.x1, rel_coords.y1, coords_bg_w, coords_bg_h, bg_color); + } +#if LV_USE_NEMA_VG + else { + + nema_vg_paint_clear(draw_nema_gfx_unit->paint); + + nema_vg_paint_set_type(draw_nema_gfx_unit->paint, NEMA_VG_PAINT_GRAD_LINEAR); + nema_vg_set_blend(NEMA_BL_SRC_OVER | NEMA_BLOP_SRC_PREMULT); + + float stops[LV_GRADIENT_MAX_STOPS]; + color_var_t colors[LV_GRADIENT_MAX_STOPS]; + + uint32_t cnt = LV_MAX(dsc->grad.stops_count, LV_GRADIENT_MAX_STOPS); + + for(uint8_t i = 0; i < cnt; i++) { + stops[i] = (float)(dsc->grad.stops[i].frac) / 255.f; + colors[i].a = LV_OPA_MIX2(dsc->grad.stops[i].opa, dsc->opa); + colors[i].r = dsc->grad.stops[i].color.red; + colors[i].g = dsc->grad.stops[i].color.green; + colors[i].b = dsc->grad.stops[i].color.blue; + } + + nema_vg_grad_set(draw_nema_gfx_unit->gradient, cnt, stops, colors); + + float x0, y0, x1, y1; + + if(dsc->grad.dir == LV_GRAD_DIR_HOR) { + x0 = rel_coords.x1; + x1 = rel_coords.x2; + y0 = rel_coords.y1; + y1 = rel_coords.y1; + } + else { + x0 = rel_coords.x1; + x1 = rel_coords.x1; + y0 = rel_coords.y1; + y1 = rel_coords.y2; + } + + nema_vg_paint_set_grad_linear(draw_nema_gfx_unit->paint, draw_nema_gfx_unit->gradient, x0, y0, x1, y1, + NEMA_TEX_CLAMP | NEMA_FILTER_BL); + + if(radius > 0.f) + nema_vg_draw_rounded_rect(rel_coords.x1, rel_coords.y1, coords_bg_w, coords_bg_h, radius, radius, NULL, + draw_nema_gfx_unit->paint); + else + nema_vg_draw_rect(rel_coords.x1, rel_coords.y1, coords_bg_w, coords_bg_h, NULL, draw_nema_gfx_unit->paint); + } +#endif + + nema_cl_submit(&(draw_nema_gfx_unit->cl)); + +} +#endif diff --git a/src/draw/nema_gfx/lv_draw_nema_gfx_hal.c b/src/draw/nema_gfx/lv_draw_nema_gfx_hal.c new file mode 100644 index 000000000..c82d938b2 --- /dev/null +++ b/src/draw/nema_gfx/lv_draw_nema_gfx_hal.c @@ -0,0 +1,263 @@ +/** + * @file lv_draw_nema_gfx_hal.c + * + * Global functions that implement some HAL functionality + * which Nema will call directly. + */ + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" +#if LV_USE_NEMA_GFX + +#include "../../misc/lv_types.h" +#include "../../misc/lv_assert.h" +#include "../../stdlib/lv_string.h" + +#include "config.h" +#include +#include + +#include +#include + +#include LV_NEMA_GFX_HAL_INCLUDE + +#include + +#include "tsi_malloc.h" + +extern GPU2D_HandleTypeDef hgpu2d; + +/********************* + * DEFINES + *********************/ + +#define RING_SIZE 1024 /* Ring Buffer Size in byte */ + +/* NemaGFX byte pool size in bytes. + * One byte per peixel for masking/stencling plus 10240 for additional allocations. + */ +#if defined(LV_NEMA_GFX_MAX_RESX) && defined(LV_NEMA_GFX_MAX_RESY) + #define NEMAGFX_MEM_POOL_SIZE ((LV_NEMA_GFX_MAX_RESX * LV_NEMA_GFX_MAX_RESY) + 10240) +#else + /* LV_USE_NEMA_VG is 0 so masking/stencling memory is not needed. */ + #define NEMAGFX_MEM_POOL_SIZE 10240 +#endif + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +#if (USE_HAL_GPU2D_REGISTER_CALLBACKS == 1) + static void GPU2D_CommandListCpltCallback(GPU2D_HandleTypeDef * hgpu2d, uint32_t CmdListID); +#endif + +/********************** + * STATIC VARIABLES + **********************/ + +LOCATION_PRAGMA_NOLOAD("Nemagfx_Memory_Pool_Buffer") +static uint8_t nemagfx_pool_mem[NEMAGFX_MEM_POOL_SIZE]; /* NemaGFX memory pool */ + +static nema_ringbuffer_t ring_buffer_str; +static volatile int last_cl_id = -1; + +//static osSemaphoreId_t nema_irq_sem = NULL; // Declare CL IRQ semaphore + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +#if (USE_HAL_GPU2D_REGISTER_CALLBACKS == 1) + static void GPU2D_CommandListCpltCallback(GPU2D_HandleTypeDef * hgpu2d, uint32_t CmdListID) +#else + void HAL_GPU2D_CommandListCpltCallback(GPU2D_HandleTypeDef * hgpu2d, uint32_t CmdListID) +#endif +{ + LV_UNUSED(hgpu2d); + + last_cl_id = CmdListID; + + /* Return a token back to a semaphore */ + // osSemaphoreRelease(nema_irq_sem); +} + +int32_t nema_sys_init(void) +{ + int error_code = 0; + + /* Setup GPU2D Callback */ +#if (USE_HAL_GPU2D_REGISTER_CALLBACKS == 1) + /* Register Command List Comlete Callback */ + HAL_GPU2D_RegisterCommandListCpltCallback(&hgpu2d, GPU2D_CommandListCpltCallback); +#endif + + /* Create IRQ semaphore */ + // nema_irq_sem = osSemaphoreNew(1, 1, NULL); + // assert(nema_irq_sem != NULL); + + /* Initialise Mem Space */ + error_code = tsi_malloc_init_pool_aligned(0, (void *)nemagfx_pool_mem, (uintptr_t)nemagfx_pool_mem, + NEMAGFX_MEM_POOL_SIZE, 1, 8); + LV_ASSERT(error_code == 0); + + /* Allocate ring_buffer memory */ + ring_buffer_str.bo = nema_buffer_create(RING_SIZE); + LV_ASSERT(ring_buffer_str.bo.base_virt); + + /* Initialize Ring Buffer */ + error_code = nema_rb_init(&ring_buffer_str, 1); + if(error_code < 0) { + return error_code; + } + + /* Reset last_cl_id counter */ + last_cl_id = 0; + + return error_code; +} + +uint32_t nema_reg_read(uint32_t reg) +{ + return HAL_GPU2D_ReadRegister(&hgpu2d, reg); +} + +void nema_reg_write(uint32_t reg, uint32_t value) +{ + HAL_GPU2D_WriteRegister(&hgpu2d, reg, value); +} + + + + +int nema_wait_irq(void) +{ + return 0; +} + + +int nema_wait_irq_cl(int cl_id) +{ + while(last_cl_id < cl_id) { + (void)nema_wait_irq(); + } + + return 0; +} + +int nema_wait_irq_brk(int brk_id) +{ + while(nema_reg_read(GPU2D_BREAKPOINT) == 0U) { + (void)nema_wait_irq(); + } + + return 0; +} + +void nema_host_free(void * ptr) +{ + tsi_free(ptr); +} + +void * nema_host_malloc(unsigned size) +{ + return tsi_malloc(size); +} + +nema_buffer_t nema_buffer_create(int size) +{ + nema_buffer_t bo; + lv_memset(&bo, 0, sizeof(bo)); + bo.base_virt = tsi_malloc(size); + bo.base_phys = (uint32_t)bo.base_virt; + bo.size = size; + LV_ASSERT_MSG(bo.base_virt != 0, "Unable to allocate memory in nema_buffer_create"); + + return bo; +} + +nema_buffer_t nema_buffer_create_pool(int pool, int size) +{ + LV_UNUSED(pool); + + return nema_buffer_create(size); +} + +void * nema_buffer_map(nema_buffer_t * bo) +{ + return bo->base_virt; +} + +void nema_buffer_unmap(nema_buffer_t * bo) +{ + LV_UNUSED(bo); +} + +void nema_buffer_destroy(nema_buffer_t * bo) +{ + if(bo->fd == -1) { + return; /* Buffer weren't allocated! */ + } + + tsi_free(bo->base_virt); + + bo->base_virt = (void *)0; + bo->base_phys = 0; + bo->size = 0; + bo->fd = -1; /* Buffer not allocated */ +} + +uintptr_t nema_buffer_phys(nema_buffer_t * bo) +{ + return bo->base_phys; +} + +void nema_buffer_flush(nema_buffer_t * bo) +{ + LV_UNUSED(bo); +} + +int nema_mutex_lock(int mutex_id) +{ + int retval = 0; + + LV_UNUSED(mutex_id); + + return retval; +} + +int nema_mutex_unlock(int mutex_id) +{ + int retval = 0; + + LV_UNUSED(mutex_id); + + return retval; +} + +void platform_disable_cache(void) +{ + +} + +void platform_invalidate_cache(void) +{ + +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +#endif /* LV_USE_NEMA_GFX */ diff --git a/src/draw/nema_gfx/lv_draw_nema_gfx_img.c b/src/draw/nema_gfx/lv_draw_nema_gfx_img.c new file mode 100644 index 000000000..e6eaa21b7 --- /dev/null +++ b/src/draw/nema_gfx/lv_draw_nema_gfx_img.c @@ -0,0 +1,223 @@ +/** + * MIT License + * + * ----------------------------------------------------------------------------- + * Copyright (c) 2008-24 Think Silicon Single Member PC + * ----------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** + * @file lv_draw_nema_gfx_fill.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_nema_gfx.h" + +#if LV_USE_NEMA_GFX + + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void _draw_nema_gfx_tile(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc, const lv_area_t * coords); + +static void _draw_nema_gfx_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc, const lv_area_t * coords); + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void _draw_nema_gfx_tile(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc, const lv_area_t * coords) +{ + + lv_image_decoder_dsc_t decoder_dsc; + lv_result_t res = lv_image_decoder_open(&decoder_dsc, dsc->src, NULL); + if(res != LV_RESULT_OK) { + LV_LOG_ERROR("Failed to open image"); + return; + } + + int32_t img_w = dsc->header.w; + int32_t img_h = dsc->header.h; + + lv_area_t tile_area; + if(lv_area_get_width(&dsc->image_area) >= 0) { + tile_area = dsc->image_area; + } + else { + tile_area = *coords; + } + lv_area_set_width(&tile_area, img_w); + lv_area_set_height(&tile_area, img_h); + + int32_t tile_x_start = tile_area.x1; + + while(tile_area.y1 <= draw_unit->clip_area->y2) { + while(tile_area.x1 <= draw_unit->clip_area->x2) { + + lv_area_t clipped_img_area; + if(lv_area_intersect(&clipped_img_area, &tile_area, draw_unit->clip_area)) { + _draw_nema_gfx_img(draw_unit, dsc, &tile_area); + } + + tile_area.x1 += img_w; + tile_area.x2 += img_w; + } + + tile_area.y1 += img_h; + tile_area.y2 += img_h; + tile_area.x1 = tile_x_start; + tile_area.x2 = tile_x_start + img_w - 1; + } + + lv_image_decoder_close(&decoder_dsc); +} + +static void _draw_nema_gfx_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc, const lv_area_t * coords) +{ + if(dsc->opa <= LV_OPA_MIN) return; + + lv_draw_nema_gfx_unit_t * draw_nema_gfx_unit = (lv_draw_nema_gfx_unit_t *)draw_unit; + + lv_layer_t * layer = draw_unit->target_layer; + const lv_image_dsc_t * img_dsc = dsc->src; + + lv_area_t blend_area; + /*Let's get the blend area which is the intersection of the area to fill and the clip area.*/ + if(!lv_area_intersect(&blend_area, coords, draw_unit->clip_area)) + return; /*Fully clipped, nothing to do*/ + + lv_area_t rel_clip_area; + lv_area_copy(&rel_clip_area, draw_unit->clip_area); + lv_area_move(&rel_clip_area, -layer->buf_area.x1, -layer->buf_area.y1); + + bool has_transform = (dsc->rotation != 0 || dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE); + /* bool recolor = (dsc->recolor_opa > LV_OPA_MIN); */ + + /*Make the blend area relative to the buffer*/ + lv_area_move(&blend_area, -layer->buf_area.x1, -layer->buf_area.y1); + + uint32_t tex_w = lv_area_get_width(coords); + uint32_t tex_h = lv_area_get_height(coords); + + nema_set_clip(rel_clip_area.x1, rel_clip_area.y1, lv_area_get_width(&rel_clip_area), + lv_area_get_height(&rel_clip_area)); + + lv_color_format_t dst_cf = layer->draw_buf->header.cf; + uint32_t dst_nema_cf = lv_nemagfx_cf_to_nema(dst_cf); + + const void * src_buf = img_dsc->data; + + uint32_t blending_mode = lv_nemagfx_blending_mode(dsc->blend_mode); + + lv_color_format_t src_cf = img_dsc->header.cf; + + /*Image contains Alpha*/ + if(src_cf == LV_COLOR_FORMAT_ARGB8888 || src_cf == LV_COLOR_FORMAT_XRGB8888) { + blending_mode |= NEMA_BLOP_SRC_PREMULT; + } + + uint32_t src_nema_cf = lv_nemagfx_cf_to_nema(src_cf); + uint32_t src_stride = img_dsc->header.stride; + + nema_bind_dst_tex((uintptr_t)NEMA_VIRT2PHYS(layer->draw_buf->data), lv_area_get_width(&(layer->buf_area)), + lv_area_get_height(&(layer->buf_area)), dst_nema_cf, + lv_area_get_width(&(layer->buf_area))*lv_color_format_get_size(dst_cf)); + + nema_bind_src_tex((uintptr_t)(src_buf), tex_w, tex_h, src_nema_cf, src_stride, + dsc->antialias ? NEMA_FILTER_BL : NEMA_FILTER_PS); + + /* if(recolor) { + lv_color32_t col32 = lv_color_to_32(dsc->recolor, LV_OPA_MIX2(dsc->recolor_opa, dsc->opa)); + uint32_t color = nema_rgba(col32.red, col32.green, col32.blue, col32.alpha); + nema_set_recolor_color(color); + blending_mode |= NEMA_BLOP_RECOLOR; + } */ + + if(dsc->opa < 255) { + uint32_t rgba = ((uint32_t)dsc->opa << 24U) | ((uint32_t)dsc->opa << 16U) | ((uint32_t)dsc->opa << 8U) | (( + uint32_t)dsc->opa); + nema_set_const_color(rgba); + blending_mode |= NEMA_BLOP_MODULATE_A; + } + + nema_set_blend_blit(blending_mode); + + if(!has_transform) { + nema_blit_rect((coords->x1 - layer->buf_area.x1), + (coords->y1 - layer->buf_area.y1), tex_w, tex_h); + } + else { + /*Calculate the transformed points*/ + float x0 = (coords->x1 - layer->buf_area.x1); + float y0 = (coords->y1 - layer->buf_area.y1); + float x1 = x0 + tex_w ; + float y1 = y0; + float x2 = x0 + tex_w ; + float y2 = y0 + tex_h; + float x3 = x0 ; + float y3 = y0 + tex_h; + + nema_matrix3x3_t m; + nema_mat3x3_load_identity(m); + nema_mat3x3_translate(m, -x0, -y0); + nema_mat3x3_translate(m, -(float)dsc->pivot.x, -(float)dsc->pivot.y); + nema_mat3x3_rotate(m, (dsc->rotation / 10.0f)); /* angle is 1/10 degree */ + float scale_x = 1.f * dsc->scale_x / LV_SCALE_NONE; + float scale_y = 1.f * dsc->scale_y / LV_SCALE_NONE; + nema_mat3x3_scale(m, (float)scale_x, (float)scale_y); + nema_mat3x3_translate(m, (float)dsc->pivot.x, (float)dsc->pivot.y); + nema_mat3x3_translate(m, x0, y0); + + /*Apply Transformation Matrix to Vertices*/ + nema_mat3x3_mul_vec(m, &x0, &y0); + nema_mat3x3_mul_vec(m, &x1, &y1); + nema_mat3x3_mul_vec(m, &x2, &y2); + nema_mat3x3_mul_vec(m, &x3, &y3); + + nema_blit_quad_fit(x0, y0, + x1, y1, + x2, y2, + x3, y3); + } + + nema_cl_submit(&(draw_nema_gfx_unit->cl)); + +} +/********************** + * GLOBAL FUNCTIONS + **********************/ +void lv_draw_nema_gfx_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * dsc, const lv_area_t * coords) +{ + + if(!dsc->tile) { + _draw_nema_gfx_img(draw_unit, dsc, coords); + } + else { + _draw_nema_gfx_tile(draw_unit, dsc, coords); + } + +} +#endif diff --git a/src/draw/nema_gfx/lv_draw_nema_gfx_label.c b/src/draw/nema_gfx/lv_draw_nema_gfx_label.c new file mode 100644 index 000000000..45d093cf9 --- /dev/null +++ b/src/draw/nema_gfx/lv_draw_nema_gfx_label.c @@ -0,0 +1,608 @@ +/** + * MIT License + * + * ----------------------------------------------------------------------------- + * Copyright (c) 2008-24 Think Silicon Single Member PC + * ----------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** + * @file lv_draw_nema_gfx_fill.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_nema_gfx.h" + +#if LV_USE_NEMA_GFX +#include "../../font/lv_font.h" +#include "../../font/lv_font_fmt_txt.h" +#include "../../misc/lv_utils.h" +#include "../../misc/lv_text_private.h" + +/********************* + * DEFINES + *********************/ +#define LV_LABEL_HINT_UPDATE_TH 1024 /*Update the "hint" if the label's y coordinates have changed more then this*/ + +/*Forward declarations*/ +void nema_set_matrix(nema_matrix3x3_t m); +void nema_raster_rect(int x, int y, int w, int h); + +/********************** + * STATIC PROTOTYPES + **********************/ + +static void _draw_nema_gfx_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * glyph_draw_dsc, + lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area); + +static void _draw_label_iterate_characters(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc, + const lv_area_t * coords); + +static inline uint8_t _bpp_nema_gfx_format(lv_draw_glyph_dsc_t * glyph_draw_dsc); + +static void _draw_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * dsc, const lv_point_t * pos, + const lv_font_t * font, uint32_t letter); + +static uint32_t get_glyph_dsc_id(const lv_font_t * font, uint32_t letter); + +static int unicode_list_compare(const void * ref, const void * element) +{ + return ((int32_t)(*(uint16_t *)ref)) - ((int32_t)(*(uint16_t *)element)); +} + +static bool raw_bitmap = false; + +/********************** + * GLOBAL FUNCTIONS + **********************/ +void lv_draw_nema_gfx_label(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc, const lv_area_t * coords) +{ + if(dsc->opa <= LV_OPA_MIN) return; + + lv_layer_t * layer = draw_unit->target_layer; + + lv_area_t clip_area; + lv_area_copy(&clip_area, draw_unit->clip_area); + lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1); + + lv_color_format_t dst_cf = layer->draw_buf->header.cf; + uint32_t dst_nema_cf = lv_nemagfx_cf_to_nema(dst_cf); + + nema_bind_dst_tex((uintptr_t)NEMA_VIRT2PHYS(layer->draw_buf->data), lv_area_get_width(&(layer->buf_area)), + lv_area_get_height(&(layer->buf_area)), dst_nema_cf, + lv_area_get_width(&(layer->buf_area))*lv_color_format_get_size(dst_cf)); + + nema_set_clip(clip_area.x1, clip_area.y1, lv_area_get_width(&clip_area), lv_area_get_height(&clip_area)); + + _draw_label_iterate_characters(draw_unit, dsc, coords); + + lv_draw_nema_gfx_unit_t * draw_nema_gfx_unit = (lv_draw_nema_gfx_unit_t *)draw_unit; + nema_cl_submit(&(draw_nema_gfx_unit->cl)); + nema_cl_wait(&(draw_nema_gfx_unit->cl)); +} + +/********************** + * STATIC FUNCTIONS + **********************/ +static inline uint8_t _bpp_nema_gfx_format(lv_draw_glyph_dsc_t * glyph_draw_dsc) +{ + uint32_t format = glyph_draw_dsc->g->format; + + switch(format) { + case LV_FONT_GLYPH_FORMAT_A1: + return NEMA_A1; + case LV_FONT_GLYPH_FORMAT_A2: + return NEMA_A2; + case LV_FONT_GLYPH_FORMAT_A4: + return NEMA_A4; + default: + return NEMA_A8; + } +} + +static void _draw_nema_gfx_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * glyph_draw_dsc, + lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area) +{ + if(glyph_draw_dsc) { + if(glyph_draw_dsc->format == LV_FONT_GLYPH_FORMAT_NONE) { +#if LV_USE_FONT_PLACEHOLDER + /* Draw a placeholder rectangle*/ + lv_draw_border_dsc_t border_draw_dsc; + lv_draw_border_dsc_init(&border_draw_dsc); + border_draw_dsc.opa = glyph_draw_dsc->opa; + border_draw_dsc.color = glyph_draw_dsc->color; + border_draw_dsc.width = 1; + lv_draw_nema_gfx_border(draw_unit, &border_draw_dsc, glyph_draw_dsc->bg_coords); +#endif + } + else if(glyph_draw_dsc->format >= LV_FONT_GLYPH_FORMAT_A1 && + glyph_draw_dsc->format <= LV_FONT_GLYPH_FORMAT_A8) { + /*Do not draw transparent things*/ + if(glyph_draw_dsc->opa <= LV_OPA_MIN) + return; + + lv_layer_t * layer = draw_unit->target_layer; + + lv_area_t blend_area; + if(!lv_area_intersect(&blend_area, glyph_draw_dsc->letter_coords, draw_unit->clip_area)) + return; + lv_area_move(&blend_area, -layer->buf_area.x1, -layer->buf_area.y1); + + const lv_draw_buf_t * draw_buf = glyph_draw_dsc->glyph_data; + const void * mask_buf = draw_buf->data; + + + int32_t x = glyph_draw_dsc->letter_coords->x1 - layer->buf_area.x1; + int32_t y = glyph_draw_dsc->letter_coords->y1 - layer->buf_area.y1; + int32_t w = glyph_draw_dsc->g->box_w; + int32_t h = glyph_draw_dsc->g->box_h; + + if(raw_bitmap) { + nema_bind_src_tex((uintptr_t)(mask_buf), w * h, 1, _bpp_nema_gfx_format(glyph_draw_dsc), 0, NEMA_FILTER_PS); + + nema_matrix3x3_t m = { + {1, w, -x - (y * w) - (0.5 * w)}, + {0, 1, 0}, + {0, 0, 1} + }; + + nema_set_matrix(m); + nema_raster_rect(x, y, w, h); + } + else { + nema_bind_src_tex((uintptr_t)(mask_buf), w, h, NEMA_A8, w, NEMA_FILTER_PS); + nema_blit(x, y); + } + } + else if(glyph_draw_dsc->format == LV_FONT_GLYPH_FORMAT_IMAGE) { +#if LV_USE_IMGFONT + lv_draw_img_dsc_t img_dsc; + lv_draw_img_dsc_init(&img_dsc); + img_dsc.angle = 0; + img_dsc.zoom = LV_ZOOM_NONE; + img_dsc.opa = glyph_draw_dsc->opa; + img_dsc.src = glyph_draw_dsc->glyph_data; + lv_draw_nema_gfx_img(draw_unit, &img_dsc, glyph_draw_dsc->letter_coords); +#endif + } + } + + if(fill_draw_dsc && fill_area) { + lv_draw_nema_gfx_fill(draw_unit, fill_draw_dsc, fill_area); + } + +} + +static inline void _set_color_blend(uint32_t color, uint8_t alpha) +{ + nema_set_tex_color(color); + + if(alpha < 255U) { + nema_set_blend_blit(NEMA_BL_SIMPLE | NEMA_BLOP_MODULATE_A); + nema_set_const_color(color); + } + else { + nema_set_blend_blit(NEMA_BL_SIMPLE); + } +} + +static void _draw_label_iterate_characters(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t * dsc, + const lv_area_t * coords) +{ + const lv_font_t * font = dsc->font; + int32_t w; + + lv_area_t clipped_area; + bool clip_ok = lv_area_intersect(&clipped_area, coords, draw_unit->clip_area); + if(!clip_ok) return; + + lv_text_align_t align = dsc->align; + lv_base_dir_t base_dir = dsc->bidi_dir; + + lv_bidi_calculate_align(&align, &base_dir, dsc->text); + + if((dsc->flag & LV_TEXT_FLAG_EXPAND) == 0) { + /*Normally use the label's width as width*/ + w = lv_area_get_width(coords); + } + else { + /*If EXPAND is enabled then not limit the text's width to the object's width*/ + lv_point_t p; + lv_text_get_size(&p, dsc->text, dsc->font, dsc->letter_space, dsc->line_space, LV_COORD_MAX, + dsc->flag); + w = p.x; + } + + int32_t line_height_font = lv_font_get_line_height(font); + int32_t line_height = line_height_font + dsc->line_space; + + /*Init variables for the first line*/ + int32_t line_width = 0; + lv_point_t pos; + lv_point_set(&pos, coords->x1, coords->y1); + + int32_t x_ofs = 0; + int32_t y_ofs = 0; + x_ofs = dsc->ofs_x; + y_ofs = dsc->ofs_y; + pos.y += y_ofs; + + uint32_t line_start = 0; + int32_t last_line_start = -1; + + /*Check the hint to use the cached info*/ + if(dsc->hint && y_ofs == 0 && coords->y1 < 0) { + /*If the label changed too much recalculate the hint.*/ + if(LV_ABS(dsc->hint->coord_y - coords->y1) > LV_LABEL_HINT_UPDATE_TH - 2 * line_height) { + dsc->hint->line_start = -1; + } + last_line_start = dsc->hint->line_start; + } + + /*Use the hint if it's valid*/ + if(dsc->hint && last_line_start >= 0) { + line_start = last_line_start; + pos.y += dsc->hint->y; + } + + uint32_t line_end = line_start + lv_text_get_next_line(&dsc->text[line_start], font, dsc->letter_space, w, NULL, + dsc->flag); + + /*Go the first visible line*/ + while(pos.y + line_height_font < draw_unit->clip_area->y1) { + /*Go to next line*/ + line_start = line_end; + line_end += lv_text_get_next_line(&dsc->text[line_start], font, dsc->letter_space, w, NULL, dsc->flag); + pos.y += line_height; + + /*Save at the threshold coordinate*/ + if(dsc->hint && pos.y >= -LV_LABEL_HINT_UPDATE_TH && dsc->hint->line_start < 0) { + dsc->hint->line_start = line_start; + dsc->hint->y = pos.y - coords->y1; + dsc->hint->coord_y = coords->y1; + } + + if(dsc->text[line_start] == '\0') return; + } + + /*Align to middle*/ + if(align == LV_TEXT_ALIGN_CENTER) { + line_width = lv_text_get_width(&dsc->text[line_start], line_end - line_start, font, dsc->letter_space); + + pos.x += (lv_area_get_width(coords) - line_width) / 2; + + } + /*Align to the right*/ + else if(align == LV_TEXT_ALIGN_RIGHT) { + line_width = lv_text_get_width(&dsc->text[line_start], line_end - line_start, font, dsc->letter_space); + pos.x += lv_area_get_width(coords) - line_width; + } + + uint32_t sel_start = dsc->sel_start; + uint32_t sel_end = dsc->sel_end; + if(sel_start > sel_end) { + uint32_t tmp = sel_start; + sel_start = sel_end; + sel_end = tmp; + } + + lv_area_t bg_coords; + lv_draw_glyph_dsc_t draw_letter_dsc; + lv_draw_glyph_dsc_init(&draw_letter_dsc); + draw_letter_dsc.opa = dsc->opa; + draw_letter_dsc.bg_coords = &bg_coords; + draw_letter_dsc.color = dsc->color; + + lv_draw_fill_dsc_t fill_dsc; + lv_draw_fill_dsc_init(&fill_dsc); + fill_dsc.opa = dsc->opa; + int32_t underline_width = font->underline_thickness ? font->underline_thickness : 1; + int32_t line_start_x; + uint32_t i; + int32_t letter_w; + + lv_color32_t dsc_col32 = lv_color_to_32(dsc->color, dsc->opa); + uint32_t nema_dsc_color = nema_rgba(dsc_col32.red, dsc_col32.green, dsc_col32.blue, dsc_col32.alpha); + lv_color32_t dsc_sel_col32 = lv_color_to_32(dsc->sel_color, dsc->opa); + uint32_t nema_dsc_sel_color = nema_rgba(dsc_sel_col32.red, dsc_sel_col32.green, dsc_sel_col32.blue, + dsc_sel_col32.alpha); + + _set_color_blend(nema_dsc_color, dsc_col32.alpha); + + uint32_t is_dsc_color_enabled = 1U; + + /*Write out all lines*/ + while(dsc->text[line_start] != '\0') { + pos.x += x_ofs; + line_start_x = pos.x; + + /*Write all letter of a line*/ + i = 0; +#if LV_USE_BIDI + char * bidi_txt = lv_malloc(line_end - line_start + 1); + LV_ASSERT_MALLOC(bidi_txt); + _lv_bidi_process_paragraph(dsc->text + line_start, bidi_txt, line_end - line_start, base_dir, NULL, 0); +#else + const char * bidi_txt = dsc->text + line_start; +#endif + + while(i < line_end - line_start) { + uint32_t logical_char_pos = 0; + if(sel_start != 0xFFFF && sel_end != 0xFFFF) { +#if LV_USE_BIDI + logical_char_pos = lv_text_encoded_get_char_id(dsc->text, line_start); + uint32_t t = lv_text_encoded_get_char_id(bidi_txt, i); + logical_char_pos += _lv_bidi_get_logical_pos(bidi_txt, NULL, line_end - line_start, base_dir, t, NULL); +#else + logical_char_pos = lv_text_encoded_get_char_id(dsc->text, line_start + i); +#endif + } + + uint32_t letter; + uint32_t letter_next; + lv_text_encoded_letter_next_2(bidi_txt, &letter, &letter_next, &i); + + letter_w = lv_font_get_glyph_width(font, letter, letter_next); + + /*Always set the bg_coordinates for placeholder drawing*/ + bg_coords.x1 = pos.x; + bg_coords.y1 = pos.y; + bg_coords.x2 = pos.x + letter_w - 1; + bg_coords.y2 = pos.y + line_height - 1; + + if(i >= line_end - line_start) { + if(dsc->decor & LV_TEXT_DECOR_UNDERLINE) { + lv_area_t fill_area; + fill_area.x1 = line_start_x; + fill_area.x2 = pos.x + letter_w - 1; + fill_area.y1 = pos.y + font->line_height - font->base_line - font->underline_position; + fill_area.y2 = fill_area.y1 + underline_width - 1; + + fill_dsc.color = dsc->color; + lv_draw_nema_gfx_fill(draw_unit, &fill_dsc, &fill_area); + } + if(dsc->decor & LV_TEXT_DECOR_STRIKETHROUGH) { + lv_area_t fill_area; + fill_area.x1 = line_start_x; + fill_area.x2 = pos.x + letter_w - 1; + fill_area.y1 = pos.y + (font->line_height - font->base_line) * 2 / 3 + font->underline_thickness / 2; + fill_area.y2 = fill_area.y1 + underline_width - 1; + + fill_dsc.color = dsc->color; + lv_draw_nema_gfx_fill(draw_unit, &fill_dsc, &fill_area); + } + } + + if(sel_start != 0xFFFF && sel_end != 0xFFFF && logical_char_pos >= sel_start && logical_char_pos < sel_end) { + draw_letter_dsc.color = dsc->sel_color; + fill_dsc.color = dsc->sel_bg_color; + lv_draw_nema_gfx_fill(draw_unit, &fill_dsc, &bg_coords); + + if(is_dsc_color_enabled) { + _set_color_blend(nema_dsc_sel_color, dsc_sel_col32.alpha); + is_dsc_color_enabled = 0U; + } + } + else { + draw_letter_dsc.color = dsc->color; + if(!is_dsc_color_enabled) { + _set_color_blend(nema_dsc_color, dsc_col32.alpha); + is_dsc_color_enabled = 1U; + } + } + + _draw_letter(draw_unit, &draw_letter_dsc, &pos, font, letter); + + if(letter_w > 0) { + pos.x += letter_w + dsc->letter_space; + } + } + +#if LV_USE_BIDI + lv_free(bidi_txt); + bidi_txt = NULL; +#endif + /*Go to next line*/ + line_start = line_end; + line_end += lv_text_get_next_line(&dsc->text[line_start], font, dsc->letter_space, w, NULL, dsc->flag); + + pos.x = coords->x1; + /*Align to middle*/ + if(align == LV_TEXT_ALIGN_CENTER) { + line_width = + lv_text_get_width(&dsc->text[line_start], line_end - line_start, font, dsc->letter_space); + + pos.x += (lv_area_get_width(coords) - line_width) / 2; + } + /*Align to the right*/ + else if(align == LV_TEXT_ALIGN_RIGHT) { + line_width = + lv_text_get_width(&dsc->text[line_start], line_end - line_start, font, dsc->letter_space); + pos.x += lv_area_get_width(coords) - line_width; + } + + /*Go the next line position*/ + pos.y += line_height; + + if(pos.y > draw_unit->clip_area->y2) break; + } + + if(draw_letter_dsc._draw_buf) lv_draw_buf_destroy(draw_letter_dsc._draw_buf); + + LV_ASSERT_MEM_INTEGRITY(); +} + +static void _draw_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * dsc, const lv_point_t * pos, + const lv_font_t * font, uint32_t letter) +{ + lv_font_glyph_dsc_t g; + + if(lv_text_is_marker(letter)) /*Markers are valid letters but should not be rendered.*/ + return; + + LV_PROFILER_BEGIN; + bool g_ret = lv_font_get_glyph_dsc(font, &g, letter, '\0'); + if(g_ret == false) { + /*Add warning if the dsc is not found*/ + LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%" LV_PRIX32, letter); + } + + /*Don't draw anything if the character is empty. E.g. space*/ + if((g.box_h == 0) || (g.box_w == 0)) { + LV_PROFILER_END; + return; + } + + lv_area_t letter_coords; + letter_coords.x1 = pos->x + g.ofs_x; + letter_coords.x2 = letter_coords.x1 + g.box_w - 1; + letter_coords.y1 = pos->y + (font->line_height - font->base_line) - g.box_h - g.ofs_y; + letter_coords.y2 = letter_coords.y1 + g.box_h - 1; + + /*If the letter is completely out of mask don't draw it*/ + if(lv_area_is_out(&letter_coords, draw_unit->clip_area, 0) && + lv_area_is_out(dsc->bg_coords, draw_unit->clip_area, 0)) { + LV_PROFILER_END; + return; + } + + if(g.resolved_font) { + lv_draw_buf_t * draw_buf = NULL; + if(LV_FONT_GLYPH_FORMAT_NONE < g.format && g.format < LV_FONT_GLYPH_FORMAT_IMAGE) { + /*Only check draw buf for bitmap glyph*/ + draw_buf = lv_draw_buf_reshape(dsc->_draw_buf, 0, g.box_w, g.box_h, LV_STRIDE_AUTO); + if(draw_buf == NULL) { + if(dsc->_draw_buf) lv_draw_buf_destroy(dsc->_draw_buf); + + uint32_t h = g.box_h; + if(h * g.box_w < 64) h *= 2; /*Alloc a slightly larger buffer*/ + draw_buf = lv_draw_buf_create(g.box_w, h, LV_COLOR_FORMAT_A8, LV_STRIDE_AUTO); + LV_ASSERT_MALLOC(draw_buf); + draw_buf->header.h = g.box_h; + dsc->_draw_buf = draw_buf; + } + } + raw_bitmap = false; + /* Performance Optimization for lv_font_fmt_txt_dsc_t fonts */ + if(font->get_glyph_bitmap == lv_font_get_bitmap_fmt_txt) { + lv_font_fmt_txt_dsc_t * fdsc = (lv_font_fmt_txt_dsc_t *)font->dsc; + if(fdsc->bitmap_format == LV_FONT_FMT_TXT_PLAIN) { + const lv_font_t * font_p = g.resolved_font; + LV_ASSERT_NULL(font_p); + + if(letter == '\t') letter = ' '; + + lv_font_fmt_txt_dsc_t * fdsc = (lv_font_fmt_txt_dsc_t *)font->dsc; + uint32_t gid = get_glyph_dsc_id(font, letter); + if(!gid) dsc->glyph_data = NULL; + + const lv_font_fmt_txt_glyph_dsc_t * gdsc = &fdsc->glyph_dsc[gid]; + + int32_t gsize = (int32_t) gdsc->box_w * gdsc->box_h; + if(gsize == 0) dsc->glyph_data = NULL; + /*NemaGFX can handle A1, A2, A4 and A8 formats, no need to allocate A8 buffers. + We will use the original font bitmap, by rewriting the data in draw_buf + */ + if(draw_buf != NULL) { + const uint8_t * bitmap_in = &fdsc->glyph_bitmap[gdsc->bitmap_index]; + draw_buf->data = (uint8_t *) bitmap_in; + } + dsc->glyph_data = (void *)draw_buf; + raw_bitmap = true; + } + } + + if(!raw_bitmap) { + dsc->glyph_data = (void *)lv_font_get_glyph_bitmap(&g, draw_buf); + } + + dsc->format = dsc->glyph_data ? g.format : LV_FONT_GLYPH_FORMAT_NONE; + } + else { + dsc->format = LV_FONT_GLYPH_FORMAT_NONE; + } + + dsc->letter_coords = &letter_coords; + dsc->g = &g; + _draw_nema_gfx_letter(draw_unit, dsc, NULL, NULL); + + if(g.resolved_font && font->release_glyph) { + lv_draw_nema_gfx_unit_t * draw_nema_gfx_unit = (lv_draw_nema_gfx_unit_t *)draw_unit; + nema_cl_submit(&(draw_nema_gfx_unit->cl)); + nema_cl_wait(&(draw_nema_gfx_unit->cl)); + font->release_glyph(font, &g); + } + LV_PROFILER_END; +} + +static uint32_t get_glyph_dsc_id(const lv_font_t * font, uint32_t letter) +{ + if(letter == '\0') return 0; + + lv_font_fmt_txt_dsc_t * fdsc = (lv_font_fmt_txt_dsc_t *)font->dsc; + + uint16_t i; + for(i = 0; i < fdsc->cmap_num; i++) { + + /*Relative code point*/ + uint32_t rcp = letter - fdsc->cmaps[i].range_start; + if(rcp >= fdsc->cmaps[i].range_length) continue; + uint32_t glyph_id = 0; + if(fdsc->cmaps[i].type == LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY) { + glyph_id = fdsc->cmaps[i].glyph_id_start + rcp; + } + else if(fdsc->cmaps[i].type == LV_FONT_FMT_TXT_CMAP_FORMAT0_FULL) { + const uint8_t * gid_ofs_8 = fdsc->cmaps[i].glyph_id_ofs_list; + glyph_id = fdsc->cmaps[i].glyph_id_start + gid_ofs_8[rcp]; + } + else if(fdsc->cmaps[i].type == LV_FONT_FMT_TXT_CMAP_SPARSE_TINY) { + uint16_t key = rcp; + uint16_t * p = lv_utils_bsearch(&key, fdsc->cmaps[i].unicode_list, fdsc->cmaps[i].list_length, + sizeof(fdsc->cmaps[i].unicode_list[0]), unicode_list_compare); + + if(p) { + lv_uintptr_t ofs = p - fdsc->cmaps[i].unicode_list; + glyph_id = fdsc->cmaps[i].glyph_id_start + ofs; + } + } + else if(fdsc->cmaps[i].type == LV_FONT_FMT_TXT_CMAP_SPARSE_FULL) { + uint16_t key = rcp; + uint16_t * p = lv_utils_bsearch(&key, fdsc->cmaps[i].unicode_list, fdsc->cmaps[i].list_length, + sizeof(fdsc->cmaps[i].unicode_list[0]), unicode_list_compare); + + if(p) { + lv_uintptr_t ofs = p - fdsc->cmaps[i].unicode_list; + const uint16_t * gid_ofs_16 = fdsc->cmaps[i].glyph_id_ofs_list; + glyph_id = fdsc->cmaps[i].glyph_id_start + gid_ofs_16[ofs]; + } + } + + return glyph_id; + } + + return 0; + +} + +#endif /*LV_USE_NEMA_GFX*/ diff --git a/src/draw/nema_gfx/lv_draw_nema_gfx_layer.c b/src/draw/nema_gfx/lv_draw_nema_gfx_layer.c new file mode 100644 index 000000000..1d9f5c74c --- /dev/null +++ b/src/draw/nema_gfx/lv_draw_nema_gfx_layer.c @@ -0,0 +1,57 @@ +/** + * MIT License + * + * ----------------------------------------------------------------------------- + * Copyright (c) 2008-24 Think Silicon Single Member PC + * ----------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** + * @file lv_draw_nema_gfx_fill.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_nema_gfx.h" + +#if LV_USE_NEMA_GFX + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_draw_nema_gfx_layer(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, const lv_area_t * coords) +{ + lv_layer_t * layer_to_draw = (lv_layer_t *)draw_dsc->src; + + /*It can happen that nothing was draw on a layer and therefore its buffer is not allocated. + *In this case just return. */ + if(layer_to_draw->draw_buf == NULL) return; + + lv_draw_image_dsc_t new_draw_dsc = *draw_dsc; + new_draw_dsc.src = layer_to_draw->draw_buf; + + lv_draw_nema_gfx_img(draw_unit, &new_draw_dsc, coords); +} + +#endif /*LV_USE_NEMA_GFX*/ \ No newline at end of file diff --git a/src/draw/nema_gfx/lv_draw_nema_gfx_line.c b/src/draw/nema_gfx/lv_draw_nema_gfx_line.c new file mode 100644 index 000000000..6ca3f8362 --- /dev/null +++ b/src/draw/nema_gfx/lv_draw_nema_gfx_line.c @@ -0,0 +1,93 @@ +/** + * MIT License + * + * ----------------------------------------------------------------------------- + * Copyright (c) 2008-24 Think Silicon Single Member PC + * ----------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** + * @file lv_draw_nema_gfx_fill.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_nema_gfx.h" + +#if LV_USE_NEMA_GFX + +/********************** + * GLOBAL FUNCTIONS + **********************/ +void lv_draw_nema_gfx_line(lv_draw_unit_t * draw_unit, const lv_draw_line_dsc_t * dsc) +{ + if(dsc->width == 0) + return; + if(dsc->opa <= (lv_opa_t)LV_OPA_MIN) + return; + if(dsc->p1.x == dsc->p2.x && dsc->p1.y == dsc->p2.y) + return; + + lv_draw_nema_gfx_unit_t * draw_nema_gfx_unit = (lv_draw_nema_gfx_unit_t *)draw_unit; + + lv_layer_t * layer = draw_unit->target_layer; + lv_area_t clip_area; + clip_area.x1 = LV_MIN(dsc->p1.x, dsc->p2.x) - dsc->width / 2; + clip_area.x2 = LV_MAX(dsc->p1.x, dsc->p2.x) + dsc->width / 2; + clip_area.y1 = LV_MIN(dsc->p1.y, dsc->p2.y) - dsc->width / 2; + clip_area.y2 = LV_MAX(dsc->p1.y, dsc->p2.y) + dsc->width / 2; + + if(!lv_area_intersect(&clip_area, &clip_area, draw_unit->clip_area)) + return; /*Fully clipped, nothing to do*/ + + lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1); + + lv_point_t point1 = {dsc->p1.x - layer->buf_area.x1, dsc->p1.y - layer->buf_area.y1}; + lv_point_t point2 = {dsc->p2.x - layer->buf_area.x1, dsc->p2.y - layer->buf_area.y1}; + + nema_set_clip(clip_area.x1, clip_area.y1, lv_area_get_width(&clip_area), lv_area_get_height(&clip_area)); + + lv_color32_t col32 = lv_color_to_32(dsc->color, dsc->opa); + + uint32_t bg_color = nema_rgba(col32.red, col32.green, col32.blue, col32.alpha); + + lv_color_format_t dst_cf = layer->draw_buf->header.cf; + uint32_t dst_nema_cf = lv_nemagfx_cf_to_nema(dst_cf); + + nema_bind_dst_tex((uintptr_t)NEMA_VIRT2PHYS(layer->draw_buf->data), lv_area_get_width(&(layer->buf_area)), + lv_area_get_height(&(layer->buf_area)), dst_nema_cf, + lv_area_get_width(&(layer->buf_area))*lv_color_format_get_size(dst_cf)); + + if(col32.alpha < 255U) { + nema_set_blend_fill(NEMA_BL_SIMPLE); + } + else { + nema_set_blend_fill(NEMA_BL_SRC); + } + + nema_draw_line_aa(point1.x, point1.y, point2.x, point2.y, dsc->width, bg_color); + + nema_cl_submit(&(draw_nema_gfx_unit->cl)); + +} +#endif \ No newline at end of file diff --git a/src/draw/nema_gfx/lv_draw_nema_gfx_triangle.c b/src/draw/nema_gfx/lv_draw_nema_gfx_triangle.c new file mode 100644 index 000000000..f500c5716 --- /dev/null +++ b/src/draw/nema_gfx/lv_draw_nema_gfx_triangle.c @@ -0,0 +1,168 @@ +/** + * MIT License + * + * ----------------------------------------------------------------------------- + * Copyright (c) 2008-24 Think Silicon Single Member PC + * ----------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** + * @file lv_draw_nema_gfx_fill.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_nema_gfx.h" + +#if LV_USE_NEMA_GFX + +/********************** + * GLOBAL FUNCTIONS + **********************/ +void lv_draw_nema_gfx_triangle(lv_draw_unit_t * draw_unit, const lv_draw_triangle_dsc_t * dsc) +{ + if(dsc->bg_opa <= LV_OPA_MIN) return; + + lv_draw_nema_gfx_unit_t * draw_nema_gfx_unit = (lv_draw_nema_gfx_unit_t *)draw_unit; + + lv_layer_t * layer = draw_unit->target_layer; + + lv_area_t rel_clip_area; + lv_area_copy(&rel_clip_area, draw_unit->clip_area); + lv_area_move(&rel_clip_area, -layer->buf_area.x1, -layer->buf_area.y1); + + lv_area_t coords; + coords.x1 = (int32_t)LV_MIN3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x); + coords.y1 = (int32_t)LV_MIN3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y); + coords.x2 = (int32_t)LV_MAX3(dsc->p[0].x, dsc->p[1].x, dsc->p[2].x); + coords.y2 = (int32_t)LV_MAX3(dsc->p[0].y, dsc->p[1].y, dsc->p[2].y); + + lv_area_move(&coords, -layer->buf_area.x1, -layer->buf_area.y1); + + lv_area_t clipped_coords; + if(!lv_area_intersect(&clipped_coords, &coords, &rel_clip_area)) + return; /* Fully clipped, nothing to do */ + + nema_set_clip(rel_clip_area.x1, rel_clip_area.y1, lv_area_get_width(&rel_clip_area), + lv_area_get_height(&rel_clip_area)); + + lv_color_format_t dst_cf = layer->draw_buf->header.cf; + uint32_t dst_nema_cf = lv_nemagfx_cf_to_nema(dst_cf); + + nema_bind_dst_tex((uintptr_t)NEMA_VIRT2PHYS(layer->draw_buf->data), lv_area_get_width(&(layer->buf_area)), + lv_area_get_height(&(layer->buf_area)), dst_nema_cf, + lv_area_get_width(&(layer->buf_area))*lv_color_format_get_size(dst_cf)); + + if(dsc->bg_grad.dir == (lv_grad_dir_t)LV_GRAD_DIR_NONE) { + + lv_color32_t col32 = lv_color_to_32(dsc->bg_color, dsc->bg_opa); + + if(col32.alpha < 255U) { + nema_set_blend_fill(NEMA_BL_SIMPLE); + } + else { + nema_set_blend_fill(NEMA_BL_SRC); + } + + uint32_t bg_color = nema_rgba(col32.red, col32.green, col32.blue, col32.alpha); + + nema_enable_aa(1, 1, 1, 0); + nema_fill_triangle(dsc->p[0].x, dsc->p[0].y, dsc->p[1].x, dsc->p[1].y, dsc->p[2].x, dsc->p[2].y, bg_color); + } +#if LV_USE_NEMA_VG + else { + + nema_vg_path_clear(draw_nema_gfx_unit->path); + nema_vg_paint_clear(draw_nema_gfx_unit->paint); + + nema_vg_paint_set_type(draw_nema_gfx_unit->paint, NEMA_VG_PAINT_GRAD_LINEAR); + nema_vg_set_blend(NEMA_BL_SRC_OVER | NEMA_BLOP_SRC_PREMULT); + nema_vg_set_fill_rule(NEMA_VG_FILL_EVEN_ODD); + + + float stops[LV_GRADIENT_MAX_STOPS]; + color_var_t colors[LV_GRADIENT_MAX_STOPS]; + + uint32_t cnt = LV_MAX(dsc->bg_grad.stops_count, LV_GRADIENT_MAX_STOPS); + + for(uint8_t i = 0; i < cnt; i++) { + stops[i] = (float)(dsc->bg_grad.stops[i].frac) / 255.f; + colors[i].a = dsc->bg_grad.stops[i].opa; + colors[i].r = dsc->bg_grad.stops[i].color.red; + colors[i].g = dsc->bg_grad.stops[i].color.green; + colors[i].b = dsc->bg_grad.stops[i].color.blue; + } + + nema_vg_grad_set(draw_nema_gfx_unit->gradient, cnt, stops, colors); + + //Calculate Bounding Box + float min_x = LV_MIN(dsc->p[0].x, dsc->p[1].x); + min_x = LV_MIN(dsc->p[2].x, min_x); + + float min_y = LV_MIN(dsc->p[0].y, dsc->p[1].y); + min_y = LV_MIN(dsc->p[2].y, min_y); + + float max_x = LV_MAX(dsc->p[0].x, dsc->p[1].x); + max_x = LV_MAX(dsc->p[2].x, max_x); + + float max_y = LV_MAX(dsc->p[0].y, dsc->p[1].y); + max_y = LV_MAX(dsc->p[2].y, max_y); + + float x0, x1, y0, y1; + + if(dsc->bg_grad.dir == LV_GRAD_DIR_HOR) { + x0 = min_x; + x1 = max_x; + y0 = min_y; + y1 = min_y; + } + else { + x0 = min_x; + x1 = min_x; + y0 = min_y; + y1 = max_y; + } + + y0 -= (float) layer->buf_area.y1; + y1 -= (float) layer->buf_area.y1; + x0 -= (float) layer->buf_area.x1; + x1 -= (float) layer->buf_area.x1; + + uint8_t cmds_polygon[] = {NEMA_VG_PRIM_MOVE, NEMA_VG_PRIM_POLYGON}; + float triangle_coords[] = {dsc->p[0].x - layer->buf_area.x1, dsc->p[0].y - layer->buf_area.y1, + 4.0f, + dsc->p[1].x - layer->buf_area.x1, dsc->p[1].y - layer->buf_area.y1, + dsc->p[2].x - layer->buf_area.x1, dsc->p[2].y - layer->buf_area.y1 + }; + nema_enable_aa(0, 0, 0, 0); + nema_vg_paint_set_grad_linear(draw_nema_gfx_unit->paint, draw_nema_gfx_unit->gradient, x0, y0, x1, y1, + NEMA_TEX_CLAMP | NEMA_FILTER_BL); + nema_vg_path_set_shape(draw_nema_gfx_unit->path, 2, cmds_polygon, 7, triangle_coords); + nema_vg_draw_path(draw_nema_gfx_unit->path, draw_nema_gfx_unit->paint); + } +#endif + + nema_cl_submit(&(draw_nema_gfx_unit->cl)); + +} +#endif diff --git a/src/draw/nema_gfx/lv_draw_nema_gfx_utils.c b/src/draw/nema_gfx/lv_draw_nema_gfx_utils.c new file mode 100644 index 000000000..db8deae68 --- /dev/null +++ b/src/draw/nema_gfx/lv_draw_nema_gfx_utils.c @@ -0,0 +1,112 @@ +/** + * MIT License + * + * ----------------------------------------------------------------------------- + * Copyright (c) 2008-24 Think Silicon Single Member PC + * ----------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** + * @file lv_draw_nema_gfx_utils.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_draw_nema_gfx.h" + +#if LV_USE_NEMA_GFX + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +uint32_t lv_nemagfx_cf_to_nema(lv_color_format_t cf) +{ + switch(cf) { + case LV_COLOR_FORMAT_A1: + return NEMA_A1; + case LV_COLOR_FORMAT_A2: + return NEMA_A2; + case LV_COLOR_FORMAT_A4: + return NEMA_A4; + case LV_COLOR_FORMAT_A8: + return NEMA_A8; + case LV_COLOR_FORMAT_I1: + return NEMA_L1; + case LV_COLOR_FORMAT_I2: + return NEMA_L2; + case LV_COLOR_FORMAT_I4: + return NEMA_L4; + case LV_COLOR_FORMAT_L8: + case LV_COLOR_FORMAT_I8: + return NEMA_L8; + case LV_COLOR_FORMAT_RGB565: + return NEMA_RGB565; + case LV_COLOR_FORMAT_RGB888: + return NEMA_BGR24; + case LV_COLOR_FORMAT_ARGB8888: + return NEMA_BGRA8888; + case LV_COLOR_FORMAT_XRGB8888: + return NEMA_BGRX8888; + default: + return LV_NEMA_GFX_COLOR_FORMAT; + } +} + +uint32_t lv_nemagfx_blending_mode(lv_blend_mode_t lv_blend_mode) +{ + uint32_t blending_mode; + switch(lv_blend_mode) { + case LV_BLEND_MODE_NORMAL: + blending_mode = NEMA_BL_SIMPLE; + break; + case LV_BLEND_MODE_ADDITIVE: + blending_mode = NEMA_BL_ADD; + break; + default: + blending_mode = NEMA_BL_SIMPLE; + break; + } + return blending_mode; +} + +void lv_nemagfx_grad_set(NEMA_VG_GRAD_HANDLE gradient, lv_grad_dsc_t lv_grad, lv_opa_t opa) +{ + + float stops[LV_GRADIENT_MAX_STOPS]; + color_var_t colors[LV_GRADIENT_MAX_STOPS]; + + uint32_t cnt = LV_MAX(lv_grad.stops_count, LV_GRADIENT_MAX_STOPS); + + for(uint8_t i = 0; i < cnt; i++) { + stops[i] = (float)(lv_grad.stops[i].frac) / 255.f; + colors[i].a = LV_OPA_MIX2(lv_grad.stops[i].opa, opa); + colors[i].r = lv_grad.stops[i].color.red; + colors[i].g = lv_grad.stops[i].color.green; + colors[i].b = lv_grad.stops[i].color.blue; + } + + nema_vg_grad_set(gradient, cnt, stops, colors); +} + +#endif /*LV_USE_NEMA_GFX*/ \ No newline at end of file diff --git a/src/draw/nema_gfx/lv_draw_nema_gfx_utils.h b/src/draw/nema_gfx/lv_draw_nema_gfx_utils.h new file mode 100644 index 000000000..f77807a11 --- /dev/null +++ b/src/draw/nema_gfx/lv_draw_nema_gfx_utils.h @@ -0,0 +1,125 @@ +/** + * MIT License + * + * ----------------------------------------------------------------------------- + * Copyright (c) 2008-24 Think Silicon Single Member PC + * ----------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next paragraph) + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** + * @file lv_draw_nema_gfx.h + * + */ + +#ifndef LV_DRAW_NEMA_GFX_UTILS_H +#define LV_DRAW_NEMA_GFX_UTILS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../lv_conf_internal.h" + +#if LV_USE_NEMA_GFX +#include "../sw/lv_draw_sw.h" + +#include "nema_core.h" +#include "nema_utils.h" +#include "nema_error.h" +#include "nema_provisional.h" +#include "nema_vg.h" + +/********************* + * DEFINES + *********************/ + +#ifndef NEMA_VIRT2PHYS +#define NEMA_VIRT2PHYS +#else +uintptr_t NEMA_VIRT2PHYS(void * addr); +#endif + +/*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/ +#if LV_COLOR_DEPTH == 8 +#define LV_NEMA_GFX_COLOR_FORMAT NEMA_L8 +#define LV_NEMA_GFX_FORMAT_MULTIPLIER 1 +#elif LV_COLOR_DEPTH == 16 +#define LV_NEMA_GFX_COLOR_FORMAT NEMA_RGB565 +#define LV_NEMA_GFX_FORMAT_MULTIPLIER 2 +#elif LV_COLOR_DEPTH == 24 +#define LV_NEMA_GFX_COLOR_FORMAT NEMA_BGR24 +#define LV_NEMA_GFX_FORMAT_MULTIPLIER 3 +#elif LV_COLOR_DEPTH == 32 +#define LV_NEMA_GFX_COLOR_FORMAT NEMA_BGRA8888 +#define LV_NEMA_GFX_FORMAT_MULTIPLIER 4 +#else +/*Can't use GPU with other formats*/ +#error Selected Color Depth Not Supported +#endif + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Convert a `lv_color_format_t` to a Nema color format. + * @param cf The LVGL color format + * @return The Nema color format + */ +uint32_t lv_nemagfx_cf_to_nema(lv_color_format_t cf); + +/** + * Get NemaGFX blending mode + * + * @param[in] lv_blend_mode The LVGL blend mode + * + * @return NemaGFX blending mode + * + */ +uint32_t lv_nemagfx_blending_mode(lv_blend_mode_t lv_blend_mode); + + +/** + * Get NemaGFX blending mode + * + * @param[in] gradient NemaGFX Gradient Buffer + * + * @param[in] lv_grad Gradient descripto + * + * @param[in] opa Descriptor's opacity + * +*/ +void lv_nemagfx_grad_set(NEMA_VG_GRAD_HANDLE gradient, lv_grad_dsc_t lv_grad, lv_opa_t opa); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_NEMA_GFX*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_DRAW_NEMA_GFX_UTILS_H*/ \ No newline at end of file diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index 439e1ad62..fe29364b4 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -583,6 +583,52 @@ #endif #endif +/*Use TSi's aka (Think Silicon) NemaGFX */ +#ifndef LV_USE_NEMA_GFX + #ifdef CONFIG_LV_USE_NEMA_GFX + #define LV_USE_NEMA_GFX CONFIG_LV_USE_NEMA_GFX + #else + #define LV_USE_NEMA_GFX 0 + #endif +#endif + +#if LV_USE_NEMA_GFX + #ifndef LV_NEMA_GFX_HAL_INCLUDE + #ifdef CONFIG_LV_NEMA_GFX_HAL_INCLUDE + #define LV_NEMA_GFX_HAL_INCLUDE CONFIG_LV_NEMA_GFX_HAL_INCLUDE + #else + #define LV_NEMA_GFX_HAL_INCLUDE + #endif + #endif + + /*Enable Vector Graphics Operations. Available only if NemaVG library is present*/ + #ifndef LV_USE_NEMA_VG + #ifdef CONFIG_LV_USE_NEMA_VG + #define LV_USE_NEMA_VG CONFIG_LV_USE_NEMA_VG + #else + #define LV_USE_NEMA_VG 0 + #endif + #endif + + #if LV_USE_NEMA_VG + /*Define application's resolution used for VG related buffer allocation */ + #ifndef LV_NEMA_GFX_MAX_RESX + #ifdef CONFIG_LV_NEMA_GFX_MAX_RESX + #define LV_NEMA_GFX_MAX_RESX CONFIG_LV_NEMA_GFX_MAX_RESX + #else + #define LV_NEMA_GFX_MAX_RESX 800 + #endif + #endif + #ifndef LV_NEMA_GFX_MAX_RESY + #ifdef CONFIG_LV_NEMA_GFX_MAX_RESY + #define LV_NEMA_GFX_MAX_RESY CONFIG_LV_NEMA_GFX_MAX_RESY + #else + #define LV_NEMA_GFX_MAX_RESY 600 + #endif + #endif + #endif +#endif + /** Use NXP's VG-Lite GPU on iMX RTxxx platforms. */ #ifndef LV_USE_DRAW_VGLITE #ifdef CONFIG_LV_USE_DRAW_VGLITE diff --git a/src/lv_init.c b/src/lv_init.c index 15aa8fd2e..0939dd8a5 100644 --- a/src/lv_init.c +++ b/src/lv_init.c @@ -40,6 +40,9 @@ #include "misc/lv_fs.h" #include "osal/lv_os_private.h" +#if LV_USE_NEMA_GFX + #include "draw/nema_gfx/lv_draw_nema_gfx.h" +#endif #if LV_USE_DRAW_VGLITE #include "draw/nxp/vglite/lv_draw_vglite.h" #endif @@ -199,6 +202,10 @@ void lv_init(void) lv_draw_sw_init(); #endif +#if LV_USE_NEMA_GFX + lv_draw_nema_gfx_init(); +#endif + #if LV_USE_DRAW_VGLITE lv_draw_vglite_init(); #endif