Cool. Now, I think we should do: WorldState MinCycleLapse: 16. So that we get a real 60FPS when moving windows around instead of the default 20 which is 50FPS, and not as smooth. Set it at 10 and it is too much, but hey, we have a lot of power these days. Try to set it to 200 and suffer :-p Phil On Mon, Oct 3, 2016 at 8:18 PM, CodeDmitry <[hidden email]> wrote: You seem to have answered my question as I was revising it D: |
In reply to this post by philippeback
Le 3/10/16 à 17:25, [hidden email]
a écrit :
Nice :) Cyril will be happy :) Stef
|
In reply to this post by Ben Coman
Thanks Ben.
I can tell you that we want to remove all such activeHand. :) One day it will come. Stef Le 3/10/16 à 12:25, Ben Coman a écrit : > On Mon, Oct 3, 2016 at 6:08 PM, Ben Coman <[hidden email]> wrote: >> On Mon, Oct 3, 2016 at 3:49 PM, CodeDmitry <[hidden email]> wrote: >>> a JavaScript timeout is a function that takes a block and a period of time, >>> and after this period of time, puts the block at the end of the event >>> queue, to be executed as soon as the runtime is done performing the tasks in >>> front of it. >>> >>> I am not sure if Pharo has an event queue, so it's a bit harder to do >>> it(since without one you can't ensure only one thing happens at a time, and >>> strange things can happen). >>> >>> That said, in simplest terms, imagine writing a clock app for Pharo, which >>> updates time every second, in JS this would be done by setting an interval >>> that ticks every 1000ms, and each time places the callback function(block) >>> at the end of the event queue. >>> >>> Related: https://www.youtube.com/watch?time_continue=1&v=8aGhZQkoFbQ >> Pharo has a single threaded VM, but multiple green threads can run concurrently. >> The closest to the event loop you are thinking of most likely the >> Morphic UI Process >> which you can see using World > Tools > Process Browser. When you execute code >> from Playground it runs in that Process (note what Smalltalk >> historically (circa 1970s?) has >> called a Process is today more commonly know as a Green Thread) >> >> If you select Morphic UI Process you will see its call stack on the >> right, where an interesting method is WorldState>>doOneCycleFor: >> You can gain some insight by turning on auto-update in the Process >> Browser, then open a Browser on WorldState>>doOneCycleFor: >> and put "self haltOnce" at the top, then enable it via... >> Pharo 5: World > System > Enable halt/inspect once. >> Pharo 6: World > Debugging > Enable all break/inspect once. >> >> You will see in the Process Browser that a new Morphic UI Process is >> spawned, and the original Morphic UI Process call stack now has >> #debugProcess at the top >> and a debug window appears that you can step through. Note, since two >> UI loops are executing here, the image may lock up, but usually its >> fine so hey! live on the edge! > > I meant to ask the list about a bug I hit doing this.... > > Putting a "self haltOnce" here... > > WorldState>>doOneCycleNowFor: aWorld > DisplayScreen checkForNewScreenSize. > self haltOnce. > "process user input events" > LastCycleTime := Time millisecondClockValue. > self handsDo: [:h | > self activeHand: h. > h processEvents. > self activeHand: nil. > ]. > self activeHand: self hands first. > aWorld runStepMethods. "there are currently some variations here" > self displayWorldSafely: aWorld. > > > When stepping over "self activeHand: nil." > another debugger appears MNU: receiver of "releaseKeyboardFocus:" is nil > in GLMPagerPanePreviewMorph(Morph)>>delete > > self activeHand > releaseKeyboardFocus: self; > releaseMouseFocus: self. > > > This can obviously be fixed by wrapping "self activeHand" with an #ifNil: > but alternatively I wonder if the "self activeHand: nil" is really needed? > It seems redundant since activeHand is set at the top of the loop and > immediately after exiting the loop. > Eliminating it would reduce the propagation of #ifNil: anti-pattern. > > https://pharo.fogbugz.com/default.asp?19169 > > cheers -ben > >> In #runStepMethodsIn: you'll see "queue := self class >> deferredUIMessages" for which you enqueue items like this... >> http://forum.world.st/Issue-3562-in-pharo-Deferred-UI-messages-executed-slowly-td3228060.html >> >> After processing the deferred UI messages, each Morph's #step method >> is processed by #runLocalStepMethodsIn: >> refer... http://wiki.squeak.org/squeak/2096 >> >> The display is then rendered by #displayWorldSafely: calling... >> --> #displayWorld >> --> #displayWorld:submorphs: >> which then is a lot to trace through, but depending on the graphics >> back end eventually ends up calling... >> Canvas>>fullDrawMorph: which ultimately invokes one of many #drawOn: >> or... >> AthensCanvas>>fullDrawMorph: which ultimately invokes one of many >> #drawOnAthensCanvas: >> >> >> So, for a regular timed UI animation, you would define your custom >> morph's #step and #stepTime methods, >> and for lower level stuff you would fork like Dennis suggests. >> >> cheers -ben > |
In reply to this post by philippeback
ere is some interesting event loop stuff from Tcl.
Me too :) First I want Bloc to get out and be ready for integration to Pharo but it takes time.
Spec is not to build fun morphic things :)
|
In reply to this post by CodeDmitry
Thanks for these mails, that's actually very helpful!
I am working on a shorter syntax for animations at the moment (than GLMAnimation, Viva, Bloc-Animation), and could not find a proper equivalent to requestAnimationFrame (i.e. that would be independent of any UI yet in sync with display, and as simple as possible). My solution was to repeatedly register to deferredUIMessages, implementing an intermediate block to add a timestamp like requestAnimationFrame (works wonders http://smalltalkhub.com/#!/~ThibaultRaffaillac/Animation) Cheers, Thibault ps: I'll ask Guille asap for the state of ReactiveExtensions (lacks comments) > Also, check > > MorphicUIManager>>#spawnNewProcess > > UIProcess := [ > [World doOneCycle. Processor yield. false] whileFalse: []. > ] newProcess priority: Processor userSchedulingPriority. > UIProcess name: 'Morphic UI Process'. > UIProcess resume > > digging into doOneCycle, you'll find: > > #doOneCycleFor: aWorld > "Do one cycle of the interaction loop. This method is called *repeatedly > *when > the world is running. This is a moderately private method; a better > alternative is usually either to wait for events or to check the state of > things from #step methods." > > self interCyclePause: MinCycleLapse. > self doOneCycleNowFor: aWorld. > > > The interCyclePause is what make the UI timing alignment proper (notice > serverMode) [and some Squeak remnant mention]: > > interCyclePause: milliSecs > "delay enough that the previous cycle plus the amount of delay will equal > milliSecs. If the cycle is already expensive, then no delay occurs. > However, if the system is idly waiting for interaction from the user, the > method will delay for a proportionally long time and cause the overall CPU > usage of *Squeak* to be low. > If self serverMode returns true then, always do a complete delay of 50ms, > independant of my argument. This prevents the freezing problem described in > Mantis #6581" > > | wait wait2 | > "*a very long assignment*" > wait := self serverMode > ifTrue: [ 50 ] > ifFalse: > [ wait2 := (lastCycleTime notNil and: [CanSurrenderToOS ~~ false]) > ifFalse: [ 0 ] > ifTrue: [ lastCycleTime + milliSecs - Time millisecondClockValue ]. > > self flag: 'Issue 14754 - wait2>millisecs is only True for clock > rollover. Remove it once DelayScheduler based on microsecondClock - Ben > Coman 19.01.2015'. "*<---- maybe we want this #flag: not to be called all > the time* " > wait2 > milliSecs > ifTrue: [ 0 ] > ifFalse: [ wait2 ]. > ]. > wait > 0 ifTrue: [ (Delay forMilliseconds: wait) wait ]. "<------- wait > is not #>>wait" > > lastCycleTime := Time millisecondClockValue. > CanSurrenderToOS := true. > > Now, yeah, how do get stuff to be painted on the screen? > > Like this: > > displayWorld: aWorld submorphs: submorphs > "Update this world's display." > > | deferredUpdateMode handsToDraw allDamage | > > submorphs do: [:m | m fullBounds]. "force re-layout if needed" > self checkIfUpdateNeeded ifFalse: [^ self]. "display is already up-to-date" > > deferredUpdateMode := self doDeferredUpdatingFor: aWorld. > deferredUpdateMode ifFalse: [self assuredCanvas]. > canvas roundCornersOf: aWorld during:[ | worldDamageRects handDamageRects | > worldDamageRects := self drawWorld: aWorld submorphs: submorphs > invalidAreasOn: canvas. "repair world's damage on canvas" > "self handsDo:[:h| h noticeDamageRects: worldDamageRects]." > handsToDraw := self selectHandsToDrawForDamage: worldDamageRects. > handDamageRects := handsToDraw collect: [:h | h savePatchFrom: canvas]. > allDamage := worldDamageRects, handDamageRects. > > handsToDraw reverseDo: [:h | canvas fullDrawMorph: h]. "draw hands onto > world canvas" > ]. > "*make this true to flash damaged areas for testing*" > self class debugShowDamage ifTrue: [aWorld flashRects: allDamage color: > Color black]. > > canvas finish. > "quickly copy altered rects of canvas to Display:" > deferredUpdateMode > ifTrue: [self forceDamageToScreen: allDamage] > ifFalse: [canvas showAt: aWorld viewBox origin invalidRects: allDamage]. > handsToDraw do: [:h | h restoreSavedPatchOn: canvas]. "restore world > canvas under hands" > Display deferUpdates: false; forceDisplayUpdate. > > The VM will take care of throwing the bits to the display in various ways. > Interesting to look how it is done for Windows, OSX, and Linux. > > So you have about a full view now. > > Timing wise, there is also some interaction with the VM occuring elsewhere. > Pharo is still polling deep inside. epoll etc isn't there yet, hence the > little idle CPU usage when doing nothing. > > Good luck doing this UI trip with other platforms, not to mention change or > instrument it the way you like. > > Pharo is really cool for this as it helps in learning about a lot of things. > > Want to do sockets? > Do the high level stuff in Pharo and dig in the VM to see how it is done > down under for a set of platforms. > > Enjoy. > > Phil |
On Fri, Oct 7, 2016 at 9:14 PM, Thibault Raffaillac
<[hidden email]> wrote: > Thanks for these mails, that's actually very helpful! > I am working on a shorter syntax for animations at the moment (than GLMAnimation, Viva, Bloc-Animation), and could not find a proper equivalent to requestAnimationFrame (i.e. that would be independent of any UI yet in sync with display, and as simple as possible). > My solution was to repeatedly register to deferredUIMessages, implementing an intermediate block to add a timestamp like requestAnimationFrame (works wonders http://smalltalkhub.com/#!/~ThibaultRaffaillac/Animation) > > Cheers, > Thibault > > ps: I'll ask Guille asap for the state of ReactiveExtensions (lacks comments) > >> Also, check >> >> MorphicUIManager>>#spawnNewProcess >> >> UIProcess := [ >> [World doOneCycle. Processor yield. false] whileFalse: []. >> ] newProcess priority: Processor userSchedulingPriority. >> UIProcess name: 'Morphic UI Process'. >> UIProcess resume >> >> digging into doOneCycle, you'll find: >> >> #doOneCycleFor: aWorld >> "Do one cycle of the interaction loop. This method is called *repeatedly >> *when >> the world is running. This is a moderately private method; a better >> alternative is usually either to wait for events or to check the state of >> things from #step methods." >> >> self interCyclePause: MinCycleLapse. >> self doOneCycleNowFor: aWorld. >> >> >> The interCyclePause is what make the UI timing alignment proper (notice >> serverMode) [and some Squeak remnant mention]: >> >> interCyclePause: milliSecs >> "delay enough that the previous cycle plus the amount of delay will equal >> milliSecs. If the cycle is already expensive, then no delay occurs. >> However, if the system is idly waiting for interaction from the user, the >> method will delay for a proportionally long time and cause the overall CPU >> usage of *Squeak* to be low. >> If self serverMode returns true then, always do a complete delay of 50ms, >> independant of my argument. This prevents the freezing problem described in >> Mantis #6581" >> >> | wait wait2 | >> "*a very long assignment*" >> wait := self serverMode >> ifTrue: [ 50 ] >> ifFalse: >> [ wait2 := (lastCycleTime notNil and: [CanSurrenderToOS ~~ false]) >> ifFalse: [ 0 ] >> ifTrue: [ lastCycleTime + milliSecs - Time millisecondClockValue ]. >> >> self flag: 'Issue 14754 - wait2>millisecs is only True for clock >> rollover. Remove it once DelayScheduler based on microsecondClock - Ben >> Coman 19.01.2015'. "*<---- maybe we want this #flag: not to be called all Yes, good idea. I'll see to it. cheers -ben |
In reply to this post by Thibault Raffaillac
Thibault
you should talk also with Glenn and Alain to get feedback. They will visit us in Nov. Stef Le 7/10/16 à 15:14, Thibault Raffaillac a écrit : > Thanks for these mails, that's actually very helpful! > I am working on a shorter syntax for animations at the moment (than GLMAnimation, Viva, Bloc-Animation), and could not find a proper equivalent to requestAnimationFrame (i.e. that would be independent of any UI yet in sync with display, and as simple as possible). > My solution was to repeatedly register to deferredUIMessages, implementing an intermediate block to add a timestamp like requestAnimationFrame (works wonders http://smalltalkhub.com/#!/~ThibaultRaffaillac/Animation) > > Cheers, > Thibault > > ps: I'll ask Guille asap for the state of ReactiveExtensions (lacks comments) > >> Also, check >> >> MorphicUIManager>>#spawnNewProcess >> >> UIProcess := [ >> [World doOneCycle. Processor yield. false] whileFalse: []. >> ] newProcess priority: Processor userSchedulingPriority. >> UIProcess name: 'Morphic UI Process'. >> UIProcess resume >> >> digging into doOneCycle, you'll find: >> >> #doOneCycleFor: aWorld >> "Do one cycle of the interaction loop. This method is called *repeatedly >> *when >> the world is running. This is a moderately private method; a better >> alternative is usually either to wait for events or to check the state of >> things from #step methods." >> >> self interCyclePause: MinCycleLapse. >> self doOneCycleNowFor: aWorld. >> >> >> The interCyclePause is what make the UI timing alignment proper (notice >> serverMode) [and some Squeak remnant mention]: >> >> interCyclePause: milliSecs >> "delay enough that the previous cycle plus the amount of delay will equal >> milliSecs. If the cycle is already expensive, then no delay occurs. >> However, if the system is idly waiting for interaction from the user, the >> method will delay for a proportionally long time and cause the overall CPU >> usage of *Squeak* to be low. >> If self serverMode returns true then, always do a complete delay of 50ms, >> independant of my argument. This prevents the freezing problem described in >> Mantis #6581" >> >> | wait wait2 | >> "*a very long assignment*" >> wait := self serverMode >> ifTrue: [ 50 ] >> ifFalse: >> [ wait2 := (lastCycleTime notNil and: [CanSurrenderToOS ~~ false]) >> ifFalse: [ 0 ] >> ifTrue: [ lastCycleTime + milliSecs - Time millisecondClockValue ]. >> >> self flag: 'Issue 14754 - wait2>millisecs is only True for clock >> rollover. Remove it once DelayScheduler based on microsecondClock - Ben >> Coman 19.01.2015'. "*<---- maybe we want this #flag: not to be called all >> the time* " >> wait2 > milliSecs >> ifTrue: [ 0 ] >> ifFalse: [ wait2 ]. >> ]. >> wait > 0 ifTrue: [ (Delay forMilliseconds: wait) wait ]. "<------- wait >> is not #>>wait" >> >> lastCycleTime := Time millisecondClockValue. >> CanSurrenderToOS := true. >> >> Now, yeah, how do get stuff to be painted on the screen? >> >> Like this: >> >> displayWorld: aWorld submorphs: submorphs >> "Update this world's display." >> >> | deferredUpdateMode handsToDraw allDamage | >> >> submorphs do: [:m | m fullBounds]. "force re-layout if needed" >> self checkIfUpdateNeeded ifFalse: [^ self]. "display is already up-to-date" >> >> deferredUpdateMode := self doDeferredUpdatingFor: aWorld. >> deferredUpdateMode ifFalse: [self assuredCanvas]. >> canvas roundCornersOf: aWorld during:[ | worldDamageRects handDamageRects | >> worldDamageRects := self drawWorld: aWorld submorphs: submorphs >> invalidAreasOn: canvas. "repair world's damage on canvas" >> "self handsDo:[:h| h noticeDamageRects: worldDamageRects]." >> handsToDraw := self selectHandsToDrawForDamage: worldDamageRects. >> handDamageRects := handsToDraw collect: [:h | h savePatchFrom: canvas]. >> allDamage := worldDamageRects, handDamageRects. >> >> handsToDraw reverseDo: [:h | canvas fullDrawMorph: h]. "draw hands onto >> world canvas" >> ]. >> "*make this true to flash damaged areas for testing*" >> self class debugShowDamage ifTrue: [aWorld flashRects: allDamage color: >> Color black]. >> >> canvas finish. >> "quickly copy altered rects of canvas to Display:" >> deferredUpdateMode >> ifTrue: [self forceDamageToScreen: allDamage] >> ifFalse: [canvas showAt: aWorld viewBox origin invalidRects: allDamage]. >> handsToDraw do: [:h | h restoreSavedPatchOn: canvas]. "restore world >> canvas under hands" >> Display deferUpdates: false; forceDisplayUpdate. >> >> The VM will take care of throwing the bits to the display in various ways. >> Interesting to look how it is done for Windows, OSX, and Linux. >> >> So you have about a full view now. >> >> Timing wise, there is also some interaction with the VM occuring elsewhere. >> Pharo is still polling deep inside. epoll etc isn't there yet, hence the >> little idle CPU usage when doing nothing. >> >> Good luck doing this UI trip with other platforms, not to mention change or >> instrument it the way you like. >> >> Pharo is really cool for this as it helps in learning about a lot of things. >> >> Want to do sockets? >> Do the high level stuff in Pharo and dig in the VM to see how it is done >> down under for a set of platforms. >> >> Enjoy. >> >> Phil > |
Maybe this could become some kind of pillar file... But things are changing a lot these days with SDL2 etc. Any roadmap of these somewhere? Phil On Sat, Oct 8, 2016 at 7:03 PM, stepharo <[hidden email]> wrote: Thibault |
It is converging - SDL2 stabilisation - Sparta integrated into Bloc - TxText optimisation - Bloc stabilization Thales guys are starting to use it. Stef
|
Free forum by Nabble | Edit this page |