2025-08-12 2:38 AM
Hi,
I have a project derived from the demo6 from ST on the STM32U5G9J-DK1 devkit, where I want to display SVG images. The only difference is that the rounded display of the original kit has been substituted with another rounded display of the same resolution (480x480 pixels) but smaller. The PCB of the display is then different as well as the display driver chip which is driven through MIPI-DSI commands (and not using video mode of MIPI-DSI like the original demo is). I'm using latest version of TGFX 4.25.0.
All the subdemos of this demo6 project are working the same as on the original display, but not the SVG subdemo. All the .SVG images of this specific sub demo, which should animate and start bouncing on the screen, are simply not rendered at all. I only see the background image which is a .PNG file. And I can come back on the main screen as the touch display is working.
I tried to strip down this demo6 project and display a simple background .PNG image and on top of this last, some .SVG images. The background image is again displayed as it should, but none of the .SVG images.
As I've seen some other having difficulties with .SVG images I tried to change the portrait/landscape mode, without seeing any change. I tried to modify the canvas buffer size, and I didn't see any change. I checked the code inside MX_DCACHE2_Init() function and I have the two lines which were advised there.
I'm running out of ideas on the reasons why .SVG images cannot be rendered. So far, the only difference I can see is around these MIPI-DSI commands usage but since all the rest of subdemos are working as expected, I don't think that this can be related. There must be something not going well before this stage, when all the images should be rendered inside the framebuffer. But I don't understand why this is related to .SVG images rendering.
Any idea or hint are welcome.
2025-08-12 8:42 AM
@apadom wrote:I remarked something a bit odd regarding the .SVG images part of the demo6:
For all .PNG files, there are some settings you can alter.
But nothing for .SVG files.
That's because an SVG image is not stored as an image. SVG is stored as render instructions (basically a list of primitive shapes to render sequentially). Images can either be stored as uncompressed bitmaps or some type of compression that requires the mapping of a color index to a palette(the chromart peripheral supports color mapping). But for SVG that is not possible. Storing them as render instructions is a form of compression. But it takes a lot more time to render.So you are trading storage memory vs time.
2025-08-12 11:25 PM
@unsigned_char_array
Thank you for your explanations.
So if I understand you well, these instructions for the rendering of .SVG resources, are part of the code in all cases?
Why not considering these instructions in an external RAM (or Flash) for instance? For me the reading of instructions in an external RAM (or Flash), in order to get the final rendered results should be possible, no?
My concern here is that, if I create all my assets to .SVG files in order to space storage space (vs bitmap formats), regardless of this extra time for the rendering (which I can afford), the fact that I can't decide where I'm locating these assets, for instance on an external RAM (or Flash), will be an issue in the end.
Do you agree?
2025-08-13 12:25 AM
@apadom wrote:@unsigned_char_array
Thank you for your explanations.
So if I understand you well, these instructions for the rendering of .SVG resources, are part of the code in all cases?
I think so.
@apadom wrote:@unsigned_char_array
My concern here is that, if I create all my assets to .SVG files in order to space storage space (vs bitmap formats), regardless of this extra time for the rendering (which I can afford), the fact that I can't decide where I'm locating these assets, for instance on an external RAM (or Flash), will be an issue in the end.
Do you agree?
https://support.touchgfx.com/docs/development/ui-development/touchgfx-engine-features/svg
"The use of SVG images adds 5-10K of extra code in the application."
This is one time only. For each new image no new code is added.
The example they show has an SVG image that takes up 350 bytes of flash.
"This CPP code is saved in the file:generated/images/src/SVGDatabase.cpp"
You might be able to modify the build process to add this file to a different section in FLASH. But if each image is only a few hundred bytes (perhaps a few k for more complex images), then I don't see the benefit of trying to relocate it.
2025-08-13 12:39 AM
Thank you for these explanations and links.
I was more thinking about offloading all .SVG (and Fonts) in an external RAM so that the renderer could quickly access these. The internal SRAM & Flash on the U5G9 won't be enough so for sure we'll have to tweak the linkerscript to define special storage location for these assets. And so tweak the build steps as you wrote.
2025-08-13 1:39 AM
@apadom wrote:I was more thinking about offloading all .SVG (and Fonts) in an external RAM so that the renderer could quickly access these.
Well it has to be stored in flash first of course. Either internal or external flash. And then moved to RAM during initialization. I checked my SVGDatabase.cpp file and it contains 99% data. But there are two functions that return a pointer to the array and it's length (getInstance and getInstanceSize). I would not put those functions in RAM or external flash. So only the arrays in external flash. Unless you want to configure external RAM or FLASH as executable regions.
2025-08-18 4:29 AM
Regarding your inability to show SVG images, I suspect you may have disabled or downprioritized the GPU2D error interrupt. That interrupt is not only used for errors, and is needed to initialize the SVG rendering logic. You should have that enabled, and I would advise giving it the same priority as the normal GPU2D interrupt.
If that does not solve your issue, can you share how and where you hook in to transfer data to your screen?
2025-08-18 5:25 AM - edited 2025-08-18 5:25 AM
Thank you @mathiasmarkussen for your answer.
Both are with the same level of interrupts as you highlighted.
I will send you privately the relevant code you asked.
I just have to fix a hardware issue prior to that.
2025-08-18 5:46 AM
Another thing to not is that the SVGs are rendered to a stencil buffer by the GPU before being transferred to the frame buffer. You may need to handle that in you linker script, if you are not using the ones provided with the Board Setup. For example, for gcc, we include this:
FramebufferSection (NOLOAD) :
{
*(TouchGFX_Framebuffer TouchGFX_Framebuffer.*)
*(.gnu.linkonce.r.*)
. = ALIGN(0x4);
*(Nemagfx_Stencil_Buffer Nemagfx_Stencil_Buffer.*)
*(.gnu.linkonce.r.*)
. = ALIGN(0x4);
*(Nemagfx_Memory_Pool_Buffer Nemagfx_Memory_Pool_Buffer.*)
*(.gnu.linkonce.r.*)
. = ALIGN(0x4);
} >RAM
2025-08-18 8:12 AM
@mathiasmarkussen
I think you had a good catch here :)
I checked the differences in the linkerscript file between what's generated for this demo and what was modified by us for our particular display. And there's exactly these sections in linkerscript which are handled differently:
That said, I'm discovering as well that our project is based on ThreadX instead of FreeRTOS. Probably because it comes from early trials with the A9 chip variant. I'm unsure if this can explain these differences. But at least I will now focus on this particular "nemagfx" component in the code.
I noticed something a bit odd: in the genuine demo6 for the G9 board setup, everything related to the framebuffer initialization is handled inside:
\TouchGFX\Target\generated\TouchGFXGeneratedHAL.cpp
While for this stencil and memory pool buffer, everything is inside:
\TouchGFX\Target\generated\nema_hal.c
Is this related to this discussion? As it's the same "feature" (buffers initialization) I would have seen these at the same place. I have the feeling that NemaGFX is somehow treated apart.
As soon as I have my hardware fixed I will be able to test different memory initialization path for these two buffers for NemaGFX and I will update this post if the SVG rendering issue is fixed.
2025-08-19 12:29 AM
Nema_hal is for hardware abstraction, and especially initialization of GPU2D and its related buffers specifically, whereas TouchGFXGeneratedHAL/TouchGFXHAL are for handling the frame buffers that are actually drawn to the display. In general, the TouchGFX library takes care of copying from the nema buffers to the general frame buffers, so user code should be handled in TouchGFXHAL.cpp.
Regarding OS selection, that should not be an issue. You can change it to FreeRTOS using CubeMX, if you want, there is some information here: Real Time Operating System | TouchGFX Documentation
But ThreadX should work fine - for the other U5G9 discovery kit, we supply Board Setups for both FreeRTOS and ThreadX.