replica nfl jerseysreplica nfl jerseyssoccer jerseyreplica nfl jerseys forums.silverfrost.com :: View topic - Avoiding flicker with rapid %pl updates
forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Avoiding flicker with rapid %pl updates
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> ClearWin+
View previous topic :: View next topic  
Author Message
Kenneth_Smith



Joined: 18 May 2012
Posts: 801
Location: Hamilton, Lanarkshire, Scotland.

PostPosted: Wed Jan 15, 2025 12:13 pm    Post subject: Avoiding flicker with rapid %pl updates Reply with quote

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
View user's profile Send private message
Kenneth_Smith



Joined: 18 May 2012
Posts: 801
Location: Hamilton, Lanarkshire, Scotland.

PostPosted: Wed Jan 15, 2025 1:05 pm    Post subject: Reply with quote

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
View user's profile Send private message
DanRRight



Joined: 10 Mar 2008
Posts: 2911
Location: South Pole, Antarctica

PostPosted: Thu Jan 16, 2025 6:53 am    Post subject: Reply with quote

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
View user's profile Send private message
Kenneth_Smith



Joined: 18 May 2012
Posts: 801
Location: Hamilton, Lanarkshire, Scotland.

PostPosted: Thu Jan 16, 2025 11:47 am    Post subject: Reply with quote

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
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 8184
Location: Salford, UK

PostPosted: Fri Jan 17, 2025 8:31 am    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
Kenneth_Smith



Joined: 18 May 2012
Posts: 801
Location: Hamilton, Lanarkshire, Scotland.

PostPosted: Fri Jan 17, 2025 12:42 pm    Post subject: Reply with quote

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
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 8184
Location: Salford, UK

PostPosted: Fri Jan 17, 2025 2:49 pm    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
Kenneth_Smith



Joined: 18 May 2012
Posts: 801
Location: Hamilton, Lanarkshire, Scotland.

PostPosted: Sun Jan 19, 2025 11:58 am    Post subject: Reply with quote

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
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 8184
Location: Salford, UK

PostPosted: Mon Jan 20, 2025 10:35 am    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
Kenneth_Smith



Joined: 18 May 2012
Posts: 801
Location: Hamilton, Lanarkshire, Scotland.

PostPosted: Tue Jan 21, 2025 11:48 am    Post subject: Reply with quote

Paul,

Thank you for this unexpected, but very welcome enhancement.
Back to top
View user's profile Send private message
Kenneth_Smith



Joined: 18 May 2012
Posts: 801
Location: Hamilton, Lanarkshire, Scotland.

PostPosted: Thu Jan 23, 2025 2:33 am    Post subject: Reply with quote

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
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 8184
Location: Salford, UK

PostPosted: Thu Jan 23, 2025 12:32 pm    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
Kenneth_Smith



Joined: 18 May 2012
Posts: 801
Location: Hamilton, Lanarkshire, Scotland.

PostPosted: Thu Jan 23, 2025 2:21 pm    Post subject: Reply with quote

Paul,

Thanks, the proverbial penny has dropped and I can see the �recipe� now.
Back to top
View user's profile Send private message
Kenneth_Smith



Joined: 18 May 2012
Posts: 801
Location: Hamilton, Lanarkshire, Scotland.

PostPosted: Fri Jan 24, 2025 11:30 am    Post subject: Reply with quote

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
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 8184
Location: Salford, UK

PostPosted: Fri Jan 24, 2025 12:49 pm    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> ClearWin+ All times are GMT + 1 Hour
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
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