Saturday, June 10, 2017

sdlvnc redux

This time I was really planning to make something useful out of the fgui code and prove to myself that it was good enough for whatever.  But... once again something else came up that captured my attention and I lost focus.  Someday I swear I'll finish.  Just not today.

So what happened was this.  I was minding my own business, lurking on the zipit IRC channel, when someone mentioned how he wanted X11 on the zipit to serve as the remote display for some other gizmo.  And that got me thinking...  Sounds familiar?  Yeah I know, it's the same story every time.  Oh well.  I just roll with it and see where it takes me.  This time it took me back to sdlvnc -- another project I never quite finished.  But maybe things would be different this time.

Anyhow since a modern X server is a bit heavy for the poor little zipit I figured let the remote gizmo do the rendering to a local headless X11vnc server.  Then you can run the less resource hungry sdlvnc client on the zipit if you want to see it and interact with it.  After all, if that other gizmo has the horsepower to run X clients, the it can probably run an instance of the X11vnc server too.   That's a much better use of the available resources.  Of course I've visited this particular problem before, but I never quite finished, and left some serious quick-N-dirty hackery in the sdlvnc zoom code.  Also I never made it  into a real openwrt package.  It was finally time to get serious about it.

First I got the old sdlvnc code working again by compiling it right on the bleeding edge openwrt zipit. In the process I fixed a few bugs with the connection setup code that I'd known about previously, but never bothered to fix.  It felt real good to finally get those out of the way.  Next I created an openwrt project for it and got a real sdlvnc openwrt package built.  That was also quite rewarding. In the process I also fixed the ebindkeys mouse emulation code to make the zipit mouse tracking less jumpy, so there's a new package for that as well. And, since everything was moving right along, I thought I'd step it up and tackle the zoom code.

The problem here was that I'd done a quick paste of the sdl_gfx zoomSurface function into the sdlvnc code the first time around.  That function is really intended for rescaling small sprites and images, and not so much for working with the entire screen.  It worked, but the performance was awful.  That's  mostly because the linear interpolation code is only written for 32 bits per pixel surfaces, so the 16 bpp vnc screen surface had to be converted, zoomed, and then converted back for every refresh.  All of those surface copies were created and destroyed on the fly by zoomSurface, for every screen refresh.  Yikes!  That's a lot of memory, and a lot of copying. It was wasting a third of a second per refresh for a 640x480 screen on the vnc server, and was even more excruciating for bigger screens, when it didn't crash for lack of memory.  So, I decided to add a 16 bpp path through the sdl_gfx zoomSurface function to eliminate all those wasteful copies.

I scribbled lots of notes and pieced it together a tiny bit at a time in the evenings, starting from a copy of the 32 bpp zoomSurfaceRGBA subfunction in sdl_gfx. Surprisingly, two or three weeks later when I tried it on a whim, it actually worked.   That never happens.  So for the next few days I cleaned it up and ran some timing tests.  The 16bit path was running in about one third the time of the 32 bit path -- a tenth of a second or so to zoom the 640x480 screen.  Much better, but I was hoping for more.  What to do next?  I was pretty sure small constant array offsets were essentially free in modern instruction sets, whereas maintaining an extra set of nearly identical pointers was not.  So I worked up some inner loop optimizations and squeezed another 12% speed gain out of it.  I also discovered that the code runs much faster the more you zoom out because it skips over more of the inner loops.  That's a nice bonus.  So converting 640x480 to 320x240 only takes about 0.03 seconds.  I can live with that, so I think I'll call this one finished.  Here's what it looks like.

I love the way the mouse pointer also gets scaled in zoom mode.

It's almost useful at that scale.  But now you can zoom in and out pretty much at will, so that's not such a problem.

Now I just need to find some new project that'd be great to have on the zipit, if only the display fit in the 320x240 pixel zipit screen.  I'm sure I passed up a few of those over the years...

2 comments:

  1. hi, thank you for the awesome resources. I am not sure if the keyboard is mapped properly on my Z2 with IZ2JFFS. Is there a working link to keyboard shortcuts for characters like }{ and ()?

    ReplyDelete
  2. There is a picture of the keyboard layout here. http://macrofig.blogspot.com/2013/01/keeping-up-with-keys.html

    It shows a mix of keybindings from iz2s and openwrt, but it's very close for both.

    ReplyDelete