 |
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
Kenneth_Smith
Joined: 18 May 2012 Posts: 799 Location: Hamilton, Lanarkshire, Scotland.
|
Posted: Wed Jan 15, 2025 12:13 pm Post subject: Avoiding flicker with rapid %pl updates |
|
|
The discussion about sorting in another thread reminded me of the short demo program below which was sitting on my desktop.
When a %pl is embedded in a window, if it is desired to continually update the plot, for example to show the progress of a simulation, this can lead to �flicker� of the display.
One way to circumvent this is demonstrated in the program below. Replace the %pl with a %gr in the window which is to display the progress of your calculation. Use %pl[external] to plot the intermediate results to an memory resident graphics region created using create_graphics_region@, then copy from that graphics region back to the %gr that is displayed in your output window.
The sample program is not optimised, as you don�t need to create and delete the memory resident graphics region each time the function plot() is called, but the additional logic obscures the simplicity of what the sample program is illustrating.
In the sample program, a cocktail sort on a small random array is animated with the display updated every time a swap of two variables occurs, without any discernible flicker of the display.
Code: | module demo
use clrwin
implicit none
real*8 :: arr(50)
integer :: uid_gr = 1000, uid_pl = 2000, gw = 900, gh = 500
contains
integer function sort()
integer :: iw, i
i = new_data() ! New data
iw = winio@('%mn[Exit]&','exit')
iw = winio@('%^tt[Sort]%^tt[New data]&',cocktail_cb,new_data)
iw = winio@('%bg%nl%`gr&', rgb@(220,220,220), gw, gh, uid_gr)
iw = winio@('%sc',plot) !Call plot after window is initially formed
sort = 2
end function sort
integer function cocktail_cb()
call set_cursor_waiting@(1) ; call cocktailsort(arr) ; cocktail_cb = 2
call set_cursor_waiting@(0)
end function cocktail_cb
integer function new_data()
logical, save :: first = .true.
integer :: i
call random_number(arr)
if ( .not. first ) i = plot()
first = .false. ; new_data = 2
end function new_data
integer function plot()
integer :: i, iw
i = create_graphics_region@(uid_pl, gw, gh )
i = select_graphics_region@(uid_pl)
iw = winio@('%pl[native,frame,gridlines,etched,width=3,link=columns,colour=blue,'//&
'dx=5,y_max=1,dy=0.5,x-axis=@,y-axis=@,external]',&
size(arr,kind=3),0.d0,1.d0,arr)
i = copy_graphics_region@( uid_gr, 1, 1, gw, gh, uid_pl, 1, 1, gw, gh, 13369376 )
i = delete_graphics_region@(uid_pl)
call sleep1@(0.01)
plot = 2
end function plot
subroutine cocktailsort(arr)
real*8, intent(inout) :: arr(:)
integer :: startp, endp, i, k, n
real*8 :: temp
logical :: swapped
n = size(arr) ; startp = 1 ; endp = n ; swapped = .true.
do while (swapped)
call temporary_yield@()
swapped = .false.
do i = startp, endp - 1, +1
if (arr(i) > arr(i + 1)) then
temp = arr(i) ; arr(i) = arr(i + 1) ; arr(i + 1) = temp ; swapped = .true.
k = plot() ! update plot after swap
end if
end do
if (.not. swapped) exit
endp = endp - 1 ; swapped = .false.
do i = endp, startp + 1, -1
if (arr(i - 1) > arr(i)) then
temp = arr(i) ; arr(i) = arr(i - 1) ; arr(i - 1) = temp ; swapped = .true.
k = plot() ! update plot after swap
end if
end do
startp = startp + 1
end do
end subroutine cocktailsort
end module demo
program p
use demo
i = sort()
end program p |
|
|
Back to top |
|
 |
Kenneth_Smith
Joined: 18 May 2012 Posts: 799 Location: Hamilton, Lanarkshire, Scotland.
|
Posted: Wed Jan 15, 2025 1:05 pm Post subject: |
|
|
For reference here is the equivalent code, without the "no flicker" approach.
Code: | module demo
use clrwin
implicit none
real*8 :: arr(50)
integer :: gw = 900, gh = 500
contains
integer function sort()
integer :: iw, i
i = new_data() ! New data
iw = winio@('%mn[Exit]&','exit')
iw = winio@('%^tt[Sort]%^tt[New data]&',cocktail_cb,new_data)
iw = winio@('%bg%nl&',rgb@(220,220,220))
iw = winio@('%pl[native,frame,gridlines,etched,width=3,link=columns,colour=blue,'//&
'dx=5,y_max=1,dy=0.5,x-axis=@,y-axis=@]',&
gw,gh,size(arr,kind=3),0.d0,1.d0,arr)
sort = 2
end function sort
integer function cocktail_cb()
call set_cursor_waiting@(1) ; call cocktailsort(arr) ; cocktail_cb = 2
call set_cursor_waiting@(0)
end function cocktail_cb
integer function new_data()
logical, save :: first = .true.
integer :: i
call random_number(arr)
if ( .not. first ) call simpleplot_redraw@()
first = .false. ; new_data = 2
end function new_data
subroutine cocktailsort(arr)
real*8, intent(inout) :: arr(:)
integer :: startp, endp, i, k, n
real*8 :: temp
logical :: swapped
n = size(arr) ; startp = 1 ; endp = n ; swapped = .true.
do while (swapped)
call temporary_yield@()
swapped = .false.
do i = startp, endp - 1, +1
if (arr(i) > arr(i + 1)) then
temp = arr(i) ; arr(i) = arr(i + 1) ; arr(i + 1) = temp ; swapped = .true.
call simpleplot_redraw@()
call sleep1@(0.01)
end if
end do
if (.not. swapped) exit
endp = endp - 1 ; swapped = .false.
do i = endp, startp + 1, -1
if (arr(i - 1) > arr(i)) then
temp = arr(i) ; arr(i) = arr(i - 1) ; arr(i - 1) = temp ; swapped = .true.
call simpleplot_redraw@()
call sleep1@(0.01)
end if
end do
startp = startp + 1
end do
end subroutine cocktailsort
end module demo
program p
use demo
i = sort()
end program p |
|
|
Back to top |
|
 |
DanRRight
Joined: 10 Mar 2008 Posts: 2910 Location: South Pole, Antarctica
|
Posted: Thu Jan 16, 2025 6:53 am Post subject: |
|
|
Ken,
Nice, but I'd prefer if Silverfrost updated %pl and made it capable what unappreciated by the users but great Clearwin's OpenGL %og[double] is doing.Then when you would call simpleplot_redraw@() it automatically write it to the one of two currently empty buffers instead of like right now when it cleaning current plot and then do simpleplot_redraw@() making sometimes flickering. At the same time it would be cleaning buffers of another channel which has been done behind the screen hidden to the user. Then next time you call simpleplot_redraw@() it would write to another buffer which was emptied in previous step, display result and hiddenly cleaning and preparing the other buffer and so on.
Not a single line of additional code would be needed from the user or to apply any additional tricks like above or changing usual pattern of simple usage of %pl -- you just add the keyword [double] to %pl. All described above would be done behind the Clearwin hood without even user knowledge
Of course I completely understand that it is easy to say than to actually implement this.
I remember that this damn flicker annoyed me since 1993 when I first time tried it with older FTN77 DBOS and showed the movie on some conference |
|
Back to top |
|
 |
Kenneth_Smith
Joined: 18 May 2012 Posts: 799 Location: Hamilton, Lanarkshire, Scotland.
|
Posted: Thu Jan 16, 2025 11:47 am Post subject: |
|
|
Dan,
One disadvantage of the approach in my example code is that %pl[external] cannot have a callback. Understandable since you cannot detect mouse clicks etc in a memory resident graphics region, however this also means that it is not possible to take advantage of the �plot_adjust� callback reason, for example to draw additional elements on the graph. Thus my example uses [link=columns] rather than drawing these explicitly within that call back (which is the way I produce histograms).
I agree, that if possible, the functionality you described based on %og[double] (which I have not used) i.e. %pl[double] would be the ideal solution.
I posted this example of one way around the flicker problem, for any future new users of %pl who may come across this issue.
In that regard, I hope others will find it useful, i.e. when making rapid updates to a relatively simple graph. |
|
Back to top |
|
 |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8177 Location: Salford, UK
|
Posted: Fri Jan 17, 2025 8:31 am Post subject: |
|
|
Thank you for this helpful feedback.
Here are two possible alternative approaches that could be explored.
1) The subroutines FREEZE_WINDOW_CONTENTS@(hwnd) and UNFREEZE_WINDOW_CONTENTS@(hwnd) might work in this context.
2) i = SendMessage(hwnd, WM_SETREDRAW, 0, 0) and
i = SendMessage(hwnd, WM_SETREDRAW, 1, 0)
before and after might work.
The second approach is better if both work and should be tested first.
hwnd is the Windows handle of the %pl control (%lc). |
|
Back to top |
|
 |
Kenneth_Smith
Joined: 18 May 2012 Posts: 799 Location: Hamilton, Lanarkshire, Scotland.
|
Posted: Fri Jan 17, 2025 12:42 pm Post subject: |
|
|
Paul,
Thanks for the two suggestions. I investigated these this morning.
With:
Code: | call FREEZE_WINDOW_CONTENTS@(hwnd)
call simpleplot_redraw@()
call UNFREEZE_WINDOW_CONTENTS@(hwnd)
|
the flicker is not eliminated.
With:
Code: | use mswin
.
.
i = SendMessage(hwnd, WM_SETREDRAW, 0, 0)
call simpleplot_redraw@()
i = SendMessage(hwnd, WM_SETREDRAW, 1, 0)
|
the flicker is eliminated, BUT the plot remains permanently �frozen� in its initial state.
So unfortunately neither of these provide the desired end result. Perhaps I have misinterpreted what you were suggesting? |
|
Back to top |
|
 |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8177 Location: Salford, UK
|
Posted: Fri Jan 17, 2025 2:49 pm Post subject: |
|
|
Ken
Sorry to take you on a wild goose chase. I think you are right. These alternatives don't work in this context. |
|
Back to top |
|
 |
Kenneth_Smith
Joined: 18 May 2012 Posts: 799 Location: Hamilton, Lanarkshire, Scotland.
|
Posted: Sun Jan 19, 2025 11:58 am Post subject: |
|
|
No problem Paul. It was worth an hour experimenting with these. I would have been delighted if I'd caught the wild goose, (or perhaps a wild haggis at this time of year in Scotland)! |
|
Back to top |
|
 |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8177 Location: Salford, UK
|
Posted: Mon Jan 20, 2025 10:35 am Post subject: |
|
|
A new option %pl[buffered] has now been added for the next release of ClearWin+.
Thank you for the feedback that triggered this enhancement. |
|
Back to top |
|
 |
Kenneth_Smith
Joined: 18 May 2012 Posts: 799 Location: Hamilton, Lanarkshire, Scotland.
|
Posted: Tue Jan 21, 2025 11:48 am Post subject: |
|
|
Paul,
Thank you for this unexpected, but very welcome enhancement. |
|
Back to top |
|
 |
Kenneth_Smith
Joined: 18 May 2012 Posts: 799 Location: Hamilton, Lanarkshire, Scotland.
|
Posted: Thu Jan 23, 2025 2:33 am Post subject: |
|
|
After downloading the new DLLs (133) I modified the second example I posted above to test this new enhancement.
In the code below the first window that is formed does not use the %pl[buffered] option, and it flickers (as before). The second window uses the new option (which is recognised) but all I see is a blank %pl region.
I'd be grateful if others who have downloaded the new DLLs could report what happens when they compile and run this code. Or perhaps Paul can tell me where I have gone wrong?
Code: | module demo
use clrwin ; use iso_fortran_env
implicit none
real*8 :: arr(50)
integer :: gw = 900, gh = 500
contains
integer function sort()
integer :: iw, i
print*, compiler_version()
! ##### Without the new buffered option
i = new_data() ! New data
iw = winio@('%mn[Exit]&','exit')
iw = winio@('%fn[Tahoma]%ts&',1.5d0)
iw = winio@('Without new buffered option %2nl%ts&',1.d0)
iw = winio@('%^tt[Sort]%^tt[New data]&',cocktail_cb,new_data)
iw = winio@('%bg%nl&',rgb@(220,220,220))
iw = winio@('%pl[native,frame,gridlines,etched,width=3,link=columns,colour=blue,'//&
'dx=5,y_max=1,dy=0.5,x-axis=@,y-axis=@]',&
gw,gh,size(arr,kind=3),0.d0,1.d0,arr)
! ### With the new buffered option
i = new_data() ! New data
iw = winio@('%mn[Exit]&','exit')
iw = winio@('%fn[Tahoma]%ts&',1.5d0)
iw = winio@('With new buffered option %2nl%ts&',1.d0)
iw = winio@('%^tt[Sort]%^tt[New data]&',cocktail_cb,new_data)
iw = winio@('%bg%nl&',rgb@(220,220,220))
iw = winio@('%pl[native,buffered,frame,gridlines,etched,width=3,link=columns,colour=blue,'//&
'dx=5,y_max=1,dy=0.5,x-axis=@,y-axis=@]',&
gw,gh,size(arr,kind=3),0.d0,1.d0,arr)
sort = 2
end function sort
integer function cocktail_cb()
call cocktailsort(arr) ; cocktail_cb = 2
end function cocktail_cb
integer function new_data()
logical, save :: first = .true.
integer :: i
call random_number(arr)
if ( .not. first ) call simpleplot_redraw@()
first = .false. ; new_data = 2
end function new_data
subroutine cocktailsort(arr)
real*8, intent(inout) :: arr(:)
integer :: startp, endp, i, k, n
real*8 :: temp
logical :: swapped
n = size(arr) ; startp = 1 ; endp = n ; swapped = .true.
do while (swapped)
swapped = .false.
do i = startp, endp - 1, +1
if (arr(i) > arr(i + 1)) then
temp = arr(i) ; arr(i) = arr(i + 1) ; arr(i + 1) = temp ; swapped = .true.
print*, 'Calling simpleplot_redraw@()' ; call simpleplot_redraw@()
end if
end do
if (.not. swapped) exit
endp = endp - 1 ; swapped = .false.
do i = endp, startp + 1, -1
if (arr(i - 1) > arr(i)) then
temp = arr(i) ; arr(i) = arr(i - 1) ; arr(i - 1) = temp ; swapped = .true.
print*, 'Calling simpleplot_redraw@()' ; call simpleplot_redraw@()
end if
end do
startp = startp + 1
end do
print*, 'sort completed'
end subroutine cocktailsort
end module demo
program p
use demo
i = sort()
end program p |
|
|
Back to top |
|
 |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8177 Location: Salford, UK
|
Posted: Thu Jan 23, 2025 12:32 pm Post subject: |
|
|
Ken
At the moment I don't understand the logic in your new program. This is a direct adaptation of your original version...
Code: | module demo
use clrwin
implicit none
real*8 :: arr(50)
integer :: gw = 900, gh = 500
contains
integer function sort()
integer :: iw, i
i = new_data() ! New data
iw = winio@('%mn[Exit]&','exit')
iw = winio@('%^tt[Sort]%^tt[New data]&',cocktail_cb,new_data)
iw = winio@('%bg%nl%gr&', rgb@(220,220,220), gw, gh)
iw = winio@('%sc',plot) !Call plot after window is initially formed
sort = 2
end function sort
integer function cocktail_cb()
call cocktailsort(arr) ;
cocktail_cb = 2
end function cocktail_cb
integer function new_data()
logical, save :: first = .true.
integer :: i
call random_number(arr)
if ( .not. first ) i = plot()
first = .false. ; new_data = 2
end function new_data
integer function plot()
integer :: iw
iw = winio@('%pl[native,frame,gridlines,etched,width=3,link=columns,colour=blue,'//&
'dx=5,y_max=1,dy=0.5,x-axis=@,y-axis=@,external,buffered]',&
size(arr,kind=3),0.d0,1.d0,arr)
plot = 2
end function plot
subroutine cocktailsort(arr)
real*8, intent(inout) :: arr(:)
integer :: startp, endp, i, k, n
real*8 :: temp
logical :: swapped
n = size(arr) ; startp = 1 ; endp = n ; swapped = .true.
do while (swapped)
call temporary_yield@()
swapped = .false.
do i = startp, endp - 1, +1
if (arr(i) > arr(i + 1)) then
temp = arr(i) ; arr(i) = arr(i + 1) ; arr(i + 1) = temp ; swapped = .true.
k = plot() ! update plot after swap
end if
end do
if (.not. swapped) exit
endp = endp - 1 ; swapped = .false.
do i = endp, startp + 1, -1
if (arr(i - 1) > arr(i)) then
temp = arr(i) ; arr(i) = arr(i - 1) ; arr(i - 1) = temp ; swapped = .true.
k = plot() ! update plot after swap
end if
end do
startp = startp + 1
end do
end subroutine cocktailsort
end module demo
winapp
program p
use demo
i = sort()
end program p |
|
|
Back to top |
|
 |
Kenneth_Smith
Joined: 18 May 2012 Posts: 799 Location: Hamilton, Lanarkshire, Scotland.
|
Posted: Thu Jan 23, 2025 2:21 pm Post subject: |
|
|
Paul,
Thanks, the proverbial penny has dropped and I can see the �recipe� now. |
|
Back to top |
|
 |
Kenneth_Smith
Joined: 18 May 2012 Posts: 799 Location: Hamilton, Lanarkshire, Scotland.
|
Posted: Fri Jan 24, 2025 11:30 am Post subject: |
|
|
Paul,
The buffered option works well, I cobbled together a second example yesterday evening, but then got a little stuck when trying to produce a slightly more pleasing appearance for the plot.
This concerns changing the font and size of the font used by the %pl[external].
If I modify the plot function in your example from yesterday to include %fn to change the font and its size via %ts:
Code: | integer function plot()
integer :: iw
iw = winio@('%fn[Consolas]%ts&',1.2d0) ! ### Does not work here
iw = winio@('%pl[native,frame,gridlines,etched,width=3,link=columns,colour=blue,'//&
'dx=5,y_max=1,dy=0.5,x-axis=@,y-axis=@,external,buffered]',&
size(arr,kind=3),0.d0,1.d0,arr)
plot = 2
end function plot
|
this approach fails.
If I add a title to the plot I can change its font and size via winop_hdl@ :
Code: | integer function plot()
integer :: iw
integer(7) :: font_handle
iw = winio@('%fn[Consolas]%ts[1.2]%gf%sf&',font_handle)
call winop_hdl@('%pl[title_hfont]',font_handle)
iw = winio@('%pl[native,frame,gridlines,etched,width=3,link=columns,colour=blue,'//&
'Title="Cocktail sort",'//&
'dx=5,y_max=1,dy=0.5,x-axis=@,y-axis=@,external,buffered]',&
size(arr,kind=3),0.d0,1.d0,arr)
plot = 2
end function plot
|
But this leaves the axes numbers and text with very small standard text.
Is there a way to change the axes font and size in a %pl[external]? I cannot find anything in the cwplus.enh related to this.
I seem to recall being defeated on this one before, but never asked the question. |
|
Back to top |
|
 |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8177 Location: Salford, UK
|
Posted: Fri Jan 24, 2025 12:49 pm Post subject: |
|
|
Using [external] causes ClearWin+ to call Draw_Simpleplot@ without creating a window or control. The window is created via the %gr and updated via the %pl.
It may be possible to add something to ClearWin+ but at the moment these changes won't work.
It should be possible to use [buffered] without [external] by making your own calls to Draw_Simpleplot@. |
|
Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|