
Timmy Brolin
Members-
Posts
11 -
Joined
-
Last visited
Recent Profile Visitors
The recent visitors block is disabled and is not being shown to other users.
-
FYI: AA by using readback works, but will always suffer a performance penalty on SPI displays. This is because: 1. Readback adds much overhead on the SPI bus. 2. The ILI9341 display only supports SPI at max 6MHz for reading, but 10MHz for writing. You get the best font rendering performance on this display if you use gdispGFillString() or gdispGFillStringBox() to write both the background color and the text in one go, avoiding the need for readback. Particularly if you also use this patch which speeds up FillString font rendering by an additional 25%:
-
Updated patch! (I found and fixed a cornercase glitch when kerning right-justified text) FlickerlessFillstring_2.patch
-
Firstly: It was impossible for the font rendering to use the public functions gdispGStreamStart(), gdispGStreamColor() and gdispGStreamStop(), because of the mutex. So the patch make these three functions private with new names: StreamStart(), StreamColor(), StreamStop(), with public APIs gdispGStreamStart(), gdispGStreamColor(), gdispGStreamStop() handling the mutex and calling the private functions. And now to answer your question: The patch provides an option GDISP_FLICKERLESS_FILLSTRING. Turn it off, and everything is as before. Turn it on, then yes font rendering with fill will use StreamStart(), StreamColor(), StreamStop(). You may very well decide to remove the option GDISP_FLICKERLESS_FILLSTRING, and just turn the change on permanently. I just felt it was practical to have it as an option for testing purposes. Makes it easy to switch back and forth. The patch does NOT add a count parameter. That would be a driver compatibility breaking change. I just suggest that you add a count parameter in UGFX 3.0. It is an easy change with obvious advantages, given that gdisp_lld_write_color() and gdispGStreamColor() are currently called in loops in many places in UGFX.
-
There is nothing driver-specific in the patch AFAIK. Performance should be good on any driver, since it uses the generic streaming functions in gdisp which are already optimized for many types of drivers. But of course, I don't have access to every type of display driver for testing.
-
Not sure I see why the responsibility of bounding can't remain at the higher layer when a count argument is added?
-
A semi-related observation: StreamColor() / gdisp_lld_write_color() are called for every single pixel when streaming. Often in a loop like this: for(; area; area--) gdisp_lld_write_color(g); When streaming fonts, these functions are called tens of thousands of times. It would improve efficiency is these functions had a "count" argument instead. It would also be easier to map that to hardware level DMA transfers. Also, with a count argument, there would no longer be any need for streaming display drivers to implement gdisp_lld_fill_area(), since gdisp_lld_write_color(g, count) would be equally efficient. Simplifying the drivers a bit. Perhaps something to consider for version 3.0 of ugfx?
-
I have tried several different ways of doing this, and found that the attached patch is the best solution. It supports anti-aliasing, kerning, and bwfonts. It implements glyph-by-glyph streaming, which both avoids the flicker, and noticeably improves performance. The only state I have added are the streaming window coordinates and the cursor position. I use the gdisp generic streaming functions, to take full advantage of the accelerations available also for non-streaming displays. gdispFillString() previously took 47ms to draw "Hello World" in a 32pt aa font. This is now down to 35ms. So, about 25% faster. Glyph-by-glyph streaming is incompatible with kerning, so the patch implements line-by-line glyph streaming when kerning is enabled. "Hello World" with kerning previously took 55ms, and is now down to 42ms. Wordwrap is the only feature which is not supported (yet). gdispGFillStringBox() will fallback to the original implementation if GDISP_NEED_TEXT_WORDWRAP is enabled. I have tested this on a ST7789 streaming display with SPI bus. To see the difference in screen refresh flicker, just run this code: while(1) gdispFillString(0, 50, "Hello World", font, GFX_WHITE, GFX_BLACK ); FlickerlessFillstring.patch
-
Pixmaps and global double buffering both consume a lot of RAM.. True, I suppose the performance will depend on the type of display controller. At least for streaming SPI displays it should be more efficient to stream filled glyphs, than to first do a fillarea() and then plot the glyphs pixel by pixel. I'll see if I can put together a patch proposal. It might take me a week or two. Perhaps a patch without kerning support would suffice as an initial proof-of-concept?
-
Essentially change this: static void skip_pixels(struct renderstate_r *rstate, gU16 count) { rstate->x += count; while (rstate->x >= rstate->x_end) { rstate->x -= rstate->x_end - rstate->x_begin; rstate->y++; } } Into this: static void skip_pixels(struct renderstate_r *rstate, gU16 count) { write_pixels(rstate, count, 0); } Plus add some background filling around the edges, and handle kerning. And remove the fillarea(g);
-
These two functions cause a lot of flickering: gdispGFillString() gdispGFillStringBox() The root cause of the flicker is that they start by doing a background fill, and then render the text on top of that. // background fill g->p.color = bgcolor; fillarea(g); Is there not a better way to do it? Looking at the font rendering code, it seems to call function "skip_pixels()" for all pixels which has alpha=0. Would it not be possible to modify "skip_pixels()", so that it draws background color to the screen for all alpha=0 pixels when gdispGFillString() / gdispGFillStringBox() are used? That way the initial fillarea(g) could be removed, and the flickering should be gone. Without the need for any double buffering. Performance bonuses: * This change alone will improve rendering performance by significantly reducing the total number of bytes written to the display. * Further performance improvement would be possible by avoiding the gdisp_lld_write_start() + gdisp_lld_write_color() + gdisp_lld_write_stop() sequence which the font rendering is currently doing for almost every pixel, and do pixel streaming instead. There is possibly a small caveat: With kerning enabled, it might be necessary to keep track of the right-most rendered pixel on each line. To avoid having skip_pixels() overwrite parts of the previous character. But that too should be perfectly doable.