Jump to content

Problem with redrawing object within container.


Sillvers

Recommended Posts

Hi again,

I struggle with the procedure of redrawing object:(.

I'd like to write gui with element which can be move within the area

of defined container.

Currently I wrote that using function gwinRedraw((GHandle)ghContainer),

but the effect isn't satisfactory, because whole container is blinking during

redrawing procedure.

Is there any other way to redraw element in diffrent place without

necessity of redraw whole container?

Link to comment
Share on other sites

When a container gets redrawn, it first clears the entire client area and then iterates through its list of children and redraws each child. This means that whenever you move your element by even just one pixel and in the container then call gwinRedraw() everything gets redrawn and that is what causes flickering due to low hardware performance.

The implementation of the currently existing container doesn't allow partial redraws.

Depending on your needs I guess the best solution for you is to write your own (container) widget from scratch that is specifically designed to contain a number of widgets that can be moved around and it will just redraw the background area that needs to be redrawn. Of course the actual implementation depends a lot on your needs. When the background is just a solid color then it will be very straight forward. If its an arbitrary pattern that is not known then it will be a bit more difficult as you basically have to buffer the entire background.

Sadly there is no official "how to write your own widget" guide at the moment. However, it is rather easy and very straight forward. Basically a widget is nothing but a table of functions that get called by the GWIN module. There's one function that gets called when the widget is supposed to get redrawn, one function that informs the widget about touch coordinates, another function for when a key press event happened and so on. Nearly all of these functions are completely optional. As there are already a lot of different widgets available you should have enough examples to get started. If you have any question regarding the implementation of widgets we are of course very happy to help you where ever we can.

I hope that helps.

~ Tectu

Link to comment
Share on other sites

I forgot to add that the background of this moving object is image :(

Well, that doesn't make writing that custom container widget easier :D

First of all, can you please tell us what hardware you're using? Eg. the used microcontroller, the display controller, the used interface between the two and so on.

It's possible to reduce the flickering with your current solution by just caching the image or by storing the image in the native format.

~ Tectu

Link to comment
Share on other sites

A short follow up on the first post: If you'll implement your own widget and you need lists, take a look at the GQUEUE module. This module provides different (highly optimized) queues and buffers.

The GQUEUE module is used internally by the GWIN module so it's already enabled anyway. This means that it won't add extra overhead.

~ Tectu

Link to comment
Share on other sites

Have you just tried using gwinMove? You should not need to call gwinRedraw.

If that is not working the way you want it, the problem has to do with clip area generation. A normal desktop gui calculates an expose clip area and a new draw clip area. The expose area is redrawn by the parent container and then the draw area is redrawn by the widget. These areas may overlap. A desktop gui will perform clip intersection and then optimally draw the two regions.

Unfortunately for an embedded gui (such as ugfx), the clip area intersecting can lead to complex shapes which requires dynamic memory allocation of the shape tables. This is expensive in cpu and ram usage and therefore not suitable for an embedded platform.

As a shortcut to avoid these issues ugfx calculates the simplest posdible clip area which results in the parent being completely redrawn and then the children being redrawn. This causes in the flashing you mention.

In general, for an embedded project it is uncommon for widgets to need to be moved so this simpler drawing algorithm is normally fine.

One way you may be able to trick it to draw better is to mark the widget invisible, move it and then make it visible again. This may tesult in less redrawing.

Link to comment
Share on other sites

Thanks for answer :)

I tryed to use gwinMove but the effect is simillar :( - still I have to redraw whole container to delete old object from old position.

I'm working with STM32f7-discovery.

For now I haven't yet written any widget to solve my problem - but I hope that I will have enough time to do that.

During my fight :) I met another case that I don't understand. So, I inset a part of code and the question to that is - Why instead of show ghImagebox1 I have white area in this place?


wi.g.show = TRUE;
wi.g.x = 250;
wi.g.y = 40;
wi.g.width = 90;
wi.g.height = 190;
wi.g.parent = ghContainerPage0;
ghImagebox1bg = gwinImageCreate(0, &wi.g);
gwinImageOpenMemory(ghImagebox1bg, itab_slider_2bg);

// create container widget: ghContainer1
wi.g.show = TRUE;
wi.g.x = 250;
wi.g.y = 40;
wi.g.width = 90;
wi.g.height = 190;
wi.g.parent = ghContainerPage0;
wi.text = "Container1";
wi.customDraw = 0;
wi.customParam = 0;
wi.customStyle = 0;
ghContainer1 = gwinContainerCreate(0, &wi, GWIN_CONTAINER_BORDER);

// create image widget: ghImagebox1
wi.g.show = TRUE;
wi.g.x = 0; //250; - ghContainerPage0
wi.g.y = 0; //40; - ghContainerPage0
wi.g.width = 90;
wi.g.height = 190;
wi.g.parent = ghContainer1;
ghImagebox1 = gwinImageCreate(0, &wi.g);
gwinImageOpenMemory(ghImagebox1, itab_slider_2);

Link to comment
Share on other sites

When you want a background image for your container it is strongly recommended to use the corresponding rendering routine for the container: gwinContainerDraw_Image().

That function takes the gdispImage pointer as parameter and will use the supplied image as the background of the container. That will not only solve your problem but will also be a much more robust and less resource hungry solution.

The corresponding API documentation will give you more information about using this rendering function: http://api.ugfx.org/master/group___rend ... adfa961280

~ Tectu

Link to comment
Share on other sites

Ok, I will try that.

But still I don't understand why I can't write such code like:


// create image widget: ghImagebox1bg
wi.g.show = TRUE;
wi.g.x = 250;
wi.g.y = 40;
wi.g.width = 90;
wi.g.height = 190;
wi.g.parent = ghContainerPage0;
ghImagebox1bg = gwinImageCreate(0, &wi.g);
gwinImageOpenMemory(ghImagebox1bg, itab_slider_2bg);

// create image widget: ghImagebox1
wi.g.show = TRUE;
wi.g.x = 250; // ghContainerPage0
wi.g.y = 40; // ghContainerPage0
wi.g.width = 90;
wi.g.height = 190;
wi.g.parent = ghContainerPage0;
ghImagebox1 = gwinImageCreate(0, &wi.g);
gwinImageOpenMemory(ghImagebox1, itab_slider_2);

The effect of executing this code is white area in the place described by wi structure.

Did I miss something? (some ugfx configuration macro)

Link to comment
Share on other sites

There's nothing that prevents overlapping images and this should work just fine without any problems at all.

Most likely it's just that your GFILE_MAX_GFILES is not set to a large enough value (assuming that you're using ROMFS). This would prevent the second gwinImageOpenFile() call from succeeding which would result in the second image box not rendering the image which would just leave the widget area cleared with the current background color and therefore hiding the image of the underlying imagebox (which would be the case anyway).

~ Tectu

Link to comment
Share on other sites

Thanks Tectu,

I achieved satisfactory result :) by using gwinContainerDraw_Image() as Tectu mentioned in last post.

Now, background of my container is image and in that way I don't have blinking black color during

container redrawing. I don't have to change the look of image in container background so that is

enough good solution for me - I'm changing only the object in foreground of containter.

I wasn't able to paint image on image cause I opened two times one of the table which containes image and

that spoils my code.

Once more again I see that this library is good compatition for more expensive graphic libraries.

Last my question in this post - Have you done some speed tests or maybe some benchmark of your library?

Where can I find the results of this benchmarks if there are any?

Link to comment
Share on other sites

Benchmarks are tricky because they only apply for a particular hardware platform. A different platform can give very different results.

We have optimised ugfx to perform best on the types of lcd controllers found in embedded platforms, with minimal ram and tiny code. We believe that we are industry leading in that arena due to our unique video driver interface and highly optimised primitive drawing routines.

Running on a desktop emulator however our performance is only average and even poor on some (Linux with X11). That is not important however as that platform is only used as a emulation platform. Any real application for that platform would use X11 directly or ugfx with the linux framebuffer driver.

Having said all that, there is a video in the demos section of tbe ugfx website that shows the blistering performance ugfx can obtain on a real embedded device. That demo is old, platforms auch as stm32f4-discovery and f7 discovery with modern ugfx code should be significantly faster again.

Link to comment
Share on other sites

We didn't know that you were actually using an imagebox for your container background. Using the image rendering function for the container is of course a lot faster as you've seen :)

Note that you can further increase performance by caching the image (in case of it's an encoded format such as GIF). Caching an image keeps the decompressed image in RAM so drawing the image is just a matter of pushing out the pixels from RAM. In case of the STM32F7 with using the LTDC interface this is blazingly fast. Also make sure that your DMA2D is enabled to free even more CPU resources.

You can find more information about image caching here: http://wiki.ugfx.org/index.php/Images#Caching

~ Tectu

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...