GUI responsiveness (was Re: SHR first impression : it's slow ?)

Carsten Haitzler (The Rasterman) raster at rasterman.com
Fri Feb 27 15:14:44 CET 2009


On Wed, 25 Feb 2009 23:43:00 -0500 Joel Newkirk <freerunner at newkirk.us> said:

> On Wed, 25 Feb 2009 12:43:59 +0100
> Helge Hafting <helge.hafting at hist.no> wrote:
> 
> > Joel Newkirk wrote:
> 
> > > With the default.edj theme (Illume doesn't override it for Fileman,
> > > which includes Illume icons) every icon on the 'desktop' initially
> > > displays just the icon image, be it png, jpg, animated edj,
> > > whatever. When you touch the screen to scroll it, it will highlight
> > > the touched icon even if you don't actually select it.
> > Hm - it shoudln't highlight unless it actually is selected. :-/
> > >  When it highlights it, it
> > > makes visible a 'background' png behind the icon, and two or three
> > > layers of transparent pngs on top of the icon, to give the 'glass
> > > button with an icon embedded in it' effect. Even when not visible
> > > (IE, on at least all but one icon at a time) those extra pngs are
> > > there, their positions are calculated AFAIK and their bitmaps are
> > > loaded.
> > 
> > I'm not sure if I understand that. Only one icon looks like a glass 
> > button - sure. Now, I understand that illume may have precomputed the 
> > glass button look for every icon there is, spending some memory. But
> > why should that need any cpu when scrolling? The glass button effect
> > isn't applied to the other icons, so those glass images should just
> > sit in memory somewhere untouched?
> > 
> > > (again, AFAIK - those two are internals of Enlightenment and I'm
> > > guessing)  
> 
> As I said, I'm guessing, but when I removed the extra PNG images and
> leav just one, enlightenment average CPU drops and the display is more
> responsive. The glass button effect /is/ applied to every icon,
> it's just that the parts ('parts' in edc syntax) relevant to the effect
> are flagged as non-visible by default.  I'm assuming that even when a
> element in the GUI is flagged visible=0 that it still calculates its
> position onscreen, so that if you have 20 icons in Illume then you're
> trying to scroll at least 100 transparent png images. ('icon' image,
> background, shine, highlight, shadow - there are actually 9 png images
> specified, plus the icon image itself) Pasted at the end is the entire
> group "e/fileman/desktop/icon/fixed" from default.edc. You can see that
> each icon actually contains eight png images, and twelve programs,
> including six that specify animated transitions.

evas does not load the data for an image file until needed. it only loads
header. also when its in the theme its no longer a png. it's a much simpler
encoding of argb data in the .edj (still compressed tho based on the .edj
source options). it also only loads one copy once. every extra copy is just a
reference to the existing one. so as such you are only paying the cost of an
extra object, not an extra image. be it a rectangle or an image - same cost
pretty much. also remember the animation of the fade is a redraw, as is the
scroll. so they equate to the same thing actually. simply the fact that it
draws under and above 1 icon a base and overlay is the extra rendering cost.
this of course means dynamic stretching of it. also for calculations - its a
really simple one to calculate a move of an obj - its simply doing some sets of
x,y, integers. its nothing really unless you are talking 1000's of objects...

> it also doesn't help that Enlightenment is advanced enough to perform
> some very nice scaling tricks - like specifying that 6 pixels inward
> from each edge should not be stretched away from that edge, so for
> example you can have a 13x13 PNG that functions as a 6-pixel border,
> with the central pixel being scaled as large as needed, while the edges
> are only stretched in one dimension, along the edge.  Wonderful feature
> to have, but I suspect that the calculations involved in this scaling
> and other nice effects E offers are at least a slight detriment to the
> (integer) FR user experience...

actually nothing floating point here at all. all integer. evas actually scales
quite fast. considering its scaling everything on the fly... with
interpolation and/or supersampling. it has no code to cache such work (yet).

if i were you - i'd wait for the scalecache :) i have demo code that does it
but it .. is buggy. basically evas will detect is scales something to a
specific size for more than N draws then it generates a copy and keeps it and
re-uses it. :) so no need to work in the theme as its done runtime.

> > > But to make the user experience worse, whenever those extra pngs are
> > > made visible or invisible, it uses an animated fade-in/fade-out.  So
> > > every time you drag to scroll, it's busy animating a fade-out on the
> > > previously highlighted icon, animating a fade-in on the one under
> > > your finger, and scrolling all the transparent and invisible PNGs.
> > > The effect is quite attractive, if only the FR had the horsepower
> > > to manage it while running a phone, GPS, and frameworkd. :(
> > 
> > I see no fade effect. When I click an icon, it gets the "glass"
> > effect. It appear with a slight delay, but there is no visible "fade
> > in". One minute there is just the icon, the next moment it is
> > "glassed". So if much work goes into this - then it is all wasted.
> 
> If you watch an icon closely when you press your stylus against it, you
> can usually perceive the fade-in taking place, particularly if your FR
> is straining, in which case you can sometimes see a few distinct delayed
> steps.  The linear transition is set to occur in 0.2 seconds fading in,
> and 0.1 seconds fading out - so it is quite brief.  I believe it
> abides by the "Framerate" setting in Illume config (the spanner), such
> that a 30fps setting and a 0.2 second fade equal a 6-frame animation.
> You can see it in the first two program sections below, "go_active" and
> "go_passive". The thumb_gen series with the decelerated and sinusoidal
> transitions aren't used on the Illume desktop it seems, but if you for
> example open the wallpaper settings in Illume config you can observer
> thumbnails that 'zoom' out from zero size when displayed, to become
> clickable 'icons'.
> 
> > > 
> > > With the present state of my altered Illume theme (serenity.edj)
> > > I've trimmed the icons down to just the 'icon' image itself and a
> > > single png that appears behind it when highlighted.  Outside the
> > > theme itself I've disabled dropshadows and changed rendering, and
> > > disabled the battery applet display (pending debugging - it sucks
> > > CPU apparently) and it reduced Enlightenment cpu usage
> > > dramatically.  
> > > 
> > > But I found significant further savings by tweaking icons.  
> > [...]
> > I am looking forward to see all this.  :-) It should definitely
> > improve the user experience.
> > 
> > Helge Hafting
> 
> Thanks for the encouragement. :)  It's already improved my user
> experience, but in my poking about I've broken things as well, which is
> why I'm not offering the .edj to anyone yet.  I plan to start from a
> clean extraction from illume.edj and default.edj once more, applying
> only the changes confirmed to be beneficial and not cause E to segfault.
> But at the pace I'm going that'll be a couple weeks still.  Hopefully
> at that point I'll be able to offer tarball and ipk versions of the
> theme for both enlightenment in general and for elementary (shr-dialer
> and kin, paroli, Raster's alarm, shr-config, etc all use elementary) as
> well as my iconset, which consists about 85% of Oxygen icons, renamed
> to match up with our common apps.  (for a 'release' of that I think I
> should retain the original names and symlink to the ones useful for
> us)  At that time I'd be honored if the theme were of 'official'
> interest, but regardless I hope it will help nudge the distributions
> toward optimizing the default (state, not default.edj specifically)
> themes.
> 
> j
> 
> /*
> below are lines 14053 through 14438 of 'default.edc', inside
> 'default.edj', this copy extracted from FSO M5 IIRC but I believe the
> same utilized in SHR. At the top it specifies what images are required
> for this 'group', which defines a single icon on the desktop. (Illume in
> our case) It also uses 'pager_base2.png' which is defined in a global
> images stanza.  
> */
> 
>    group { name: "e/fileman/desktop/icon/fixed";
>       images {
>          image: "bt_sm_base1.png" COMP;
> 	 image: "bt_sm_shine.png" COMP;
> 	 image: "bt_sm_hilight.png" COMP;
> 
> 	 image: "e17_mini_button_shadow2.png" COMP;
> 	 image: "e17_fileman_thumb_bg.png" COMP;
> 	 image: "icon_efm_dnd_copy.png" COMP;
> 	 image: "icon_efm_dnd_ask.png" COMP;
> 	 image: "icon_efm_dnd_move.png" COMP;
>       }
>       parts {
> 	 part { name: "bg";
> 	    mouse_events: 0;
> 	    description { state: "default" 0.0;
> 	       visible: 0;
> 	       color: 255 255 255 0;
> 	       rel1 {
> 		  relative: 0.0 0.0;
> 		  offset: -5 -5;
> 	       }
> 	       rel2 {
> 		  relative: 1.0 1.0;
> 		  offset: 4 4;
> 	       }
> 	       image {
> 		  normal: "bt_sm_base1.png";
> 		  border: 6 6 6 6;
> 	       }
> 	    }
> 	    description { state: "selected" 0.0;
> 	       inherit: "default" 0.0;
> 	       visible: 1;
> 	       color: 255 255 255 255;
> 	       rel1 {
> 		  relative: 0.0 0.0;
> 		  offset: -2 -2;
> 	       }
> 	       rel2 {
> 		  relative: 1.0 1.0;
> 		  offset: 1 1;
> 	       }
> 	    }
> 	 }
> 	 part {	name: "icon_box_shadow";
> 	    mouse_events: 0;
> 	    description { state: "default" 0.0;
> 	       visible: 0;
> 	       rel1 {
> 		  to: "icon_box";
> 		  relative: 0.0 0.0;
> 		  offset: -1 -1;
> 	       }
> 	       rel2 {
> 		  to: "icon_box";
> 		  relative: 1.0 1.0;
> 		  offset: 2 2;
> 	       }
> 	       image {
> 		  normal: "e17_mini_button_shadow2.png";
> 		  border: 6 6 6 6;
> 	       }
> 	    }
> 	    description { state: "visible" 0.0;
> 	       inherit: "default" 0.0;
> 	       visible: 1;
> 	    }
> 	 }
> 	 part { name: "icon_box";
> 	    type: RECT;
> 	    mouse_events:  0;
> 	    description { state: "default" 0.0;
> 	       visible: 0;
> 	       align: 0.5 0.5;
> 	       rel1 {
> 		  to: "e.swallow.icon";
> 		  relative: 0.0 0.0;
> 		  offset: -1 -1;
> 	       }
> 	       rel2 {
> 		  to: "e.swallow.icon";
> 		  relative: 1.0 1.0;
> 		  offset: 0 0;
> 	       }
> 	       color: 0 0 0 64;
> 	    }
> 	    description { state: "visible" 0.0;
> 	       inherit: "default" 0.0;
> 	       visible: 1;
> 	    }
> 	 }
> 	 part { name: "icon_box_bg";
> 	    mouse_events:  0;
> 	    description { state: "default" 0.0;
> 	       visible: 0;
> 	       rel1 {
> 		  to: "icon_box";
> 		  relative: 0.0 0.0;
> 		  offset: 1 1;
> 	       }
> 	       rel2 {
> 		  to: "icon_box";
> 		  relative: 1.0 1.0;
> 		  offset: -2 -2;
> 	       }
> 	       image.normal: "pager_base2.png";
> 	       fill {
> 		  smooth: 0;
> 		  size {
> 		     relative: 0 0;
> 		     offset:   32 32;
> 		  }
> 	       }
> 	    }
> 	    description { state: "visible" 0.0;
> 	       inherit: "default" 0.0;
> 	       visible: 1;
> 	    }
> 	 }
> 	 part { name: "icon0";
> 	    type: RECT;
> 	    mouse_events: 0;
> 	    description { state: "default" 0.0;
> 	       align: 0.5 0.5;
> 	       aspect: 1.0 1.0;
> 	       aspect_preference: VERTICAL;
> 	       visible: 0;
> 	       rel1 {
> 		  relative: 0.0 0.0;
> 		  offset: 2 2;
> 	       }
> 	       rel2 {
> 		  to_y: "e.text.label";
> 		  relative: 1.0 0.0;
> 		  offset: -3 -1;
> 	       }
> 	       color: 0 0 0 0;
> 	    }
> 	 }
> 	 part { name: "icon";
> 	    type: RECT;
> 	    mouse_events: 0;
> 	    description { state: "default" 0.0;
> 	       align: 0.5 0.5;
> 	       aspect: 1.0 1.0;
> 	       aspect_preference: BOTH;
> 	       visible:  0;
> 	       rel1.to: "icon0";
> 	       rel2.to: "icon0";
> 	       color: 0 0 0 0;
> 	    }
> 	    description { state: "min" 0.0;
> 	       inherit: "default" 0.0;
> 	       max: 0 0;
> 	    }
> 	    description { state: "max" 0.0;
> 	       inherit: "default" 0.0;
> 	       rel1 {
> 		  to: "icon0";
> 		  relative: 0.0  0.0;
> 		  offset:   -4   -4;
> 	       }
> 	       rel2 {
> 		  to: "icon0";
> 		  relative: 1.0  1.0;
> 		  offset:   3    3;
> 	       }
> 	    }
> 	    description { state: "max2" 0.0;
> 	       inherit:  "default" 0.0;
> 	       rel1 {
> 		  to: "icon0";
> 		  relative: 0.0  0.0;
> 		  offset:   -2   -2;
> 	       }
> 	       rel2 {
> 		  to: "icon0";
> 		  relative: 1.0  1.0;
> 		  offset:   1    1;
> 	       }
> 	    }
> 	 }
> 	 part { name: "e.swallow.icon";
> 	    type: SWALLOW;
> 	    description { state: "default" 0.0;
> 	       aspect: 1.0 1.0;
> 	       aspect_preference: BOTH;
> 	       align: 0.5 0.5;
> 	       //          fixed:    1 1;
> 	       rel1.to: "icon";
> 	       rel2.to: "icon";
> 	    }
> 	 }
> 	 part { name: "e.text.label";
> 	    type: TEXT;
> 	    effect: SOFT_SHADOW;
> 	    mouse_events:  0;
> 	    scale: 1;
> 	    description { state: "default" 0.0;
> 	       align: 0.5 1.0;
> 	       fixed: 0 1;
> 	       rel1 {
> 		  relative: 0.0 1.0;
> 		  offset:   2 -2;
> 	       }
> 	       rel2 {
> 		  relative: 1.0 1.0;
> 		  offset:   -3 -2;
> 	       }
> 	       color: 224 224 224 255;
> 	       color3: 0 0 0 32;
> 	       text {
>                   font: "Sans:style=Bold";
> 		  size: 10;
> 		  min: 0 1;
> 		  align: 0.5 0.5;
> 		  text_class: "desktop_icon";
> 	       }
> 	    }
> 	    description { state: "selected" 0.0;
> 	       inherit: "default" 0.0;
> 	       color: 224 224 224 255;
> 	       color3: 0 0 0 64;
> 	    }
> 	 }
> 	 part { name: "fg1";
> 	    mouse_events: 0;
> 	    description { state: "default" 0.0;
> 	       visible: 0;
> 	       color: 255 255 255 0;
> 	       rel1.to: "bg";
> 	       rel2.relative: 1.0 0.5;
> 	       rel2.to: "bg";
> 	       image {
> 		  normal: "bt_sm_hilight.png";
> 		  border: 6 6 6 0;
> 	       }
> 	    }
> 	    description { state: "selected" 0.0;
> 	       inherit: "default" 0.0;
> 	       visible: 1;
> 	       color: 255 255 255 255;
> 	    }
> 	 }
> 	 part { name: "fg2";
> 	    mouse_events: 0;
> 	    description { state: "default" 0.0;
> 	       visible: 0;
> 	       color: 255 255 255 0;
> 	       rel1.to: "bg";
> 	       rel2.to: "bg";
> 	       image {
> 		  normal: "bt_sm_shine.png";
> 		  border: 6 6 6 0;
> 	       }
> 	    }
> 	    description { state: "selected" 0.0;
> 	       inherit: "default" 0.0;
> 	       visible: 1;
> 	       color: 255 255 255 255;
> 	    }
> 	 }
> 	 part { name: "event";
> 	    type: RECT;
> 	    mouse_events: 1;
> 	    description { state: "default" 0.0;
> 	       color: 0 0 0 0;
> 	    }
> 	 }
> 	 part { name: "dnd_action";
> 	    type: IMAGE;
> 	    mouse_events:  0;
> 	    repeat_events: 0;
> 	    description { state: "default" 0.0;
> 	       color:      0 0 0 0;
> 	    }
> 	    description { state: "visible" 0.0;
> 	       aspect: 1.0 1.0;
> 	       aspect_preference: BOTH;
> 	       align: 1.0 1.0;
> 	       min: 24 24;
> 	       rel1.relative: 0.75 0.0;
> 	       rel2.relative: 1.0 1.0;
> 	    }
> 	    description { state: "copy" 0.0;
> 	       inherit: "visible" 0.0;
> 	       image.normal:  "icon_efm_dnd_copy.png";
> 	    }
> 	    description { state: "ask" 0.0;
> 	       inherit: "visible" 0.0;
> 	       image.normal:  "icon_efm_dnd_ask.png";
> 	    }
> 	    description { state: "move" 0.0;
> 	       inherit: "visible" 0.0;
> 	       image.normal:  "icon_efm_dnd_move.png";
> 	    }
> 	 }
>       }
>       programs {
> 	 program { name: "go_active";
> 	    signal:  "e,state,selected";
> 	    source:  "e";
> 	    action:  STATE_SET "selected" 0.0;
> 	    target:  "bg";
> 	    target:  "fg1";
> 	    target:  "fg2";
> 	    target:  "e.text.label";
> 	    transition: LINEAR 0.2;
> 	 }
> 	 program { name: "go_passive";
> 	    signal:  "e,state,unselected";
> 	    source:  "e";
> 	    action:  STATE_SET "default" 0.0;
> 	    target:  "bg";
> 	    target:  "fg1";
> 	    target:  "fg2";
> 	    target:  "e.text.label";
> 	    transition: LINEAR 0.1;
> 	 }
> 	 program { name: "ask";
> 	    signal: "e,state,ask";
> 	    source: "e";
> 	    action: STATE_SET "ask" 0.0;
> 	    target: "dnd_action";
> 	 }
> 	 program { name: "move";
> 	    signal: "e,state,move";
> 	    source: "e";
> 	    action: STATE_SET "move" 0.0;
> 	    target: "dnd_action";
> 	 }
> 	 program { name: "copy";
> 	    signal: "e,state,copy";
> 	    source: "e";
> 	    action: STATE_SET "copy" 0.0;
> 	    target: "dnd_action";
> 	 }
> 	 program { name: "thumb_gen";
> 	    signal:  "e,action,thumb,gen";
> 	    source:  "e";
> 	    action:  STATE_SET "visible" 0.0;
> 	    target:  "icon_box_shadow";
> 	    target:  "icon_box";
> 	    target:  "icon_box_bg";
> 	    after:   "thumb_gen2";
> 	 }
> 	 program { name: "thumb_gen-";
> 	    signal:  "e,action,thumb,gen,alpha";
> 	    source:  "e";
> 	    action:  STATE_SET "default" 0.0;
> 	    target:  "icon_box_shadow";
> 	    target:  "icon_box";
> 	    target:  "icon_box_bg";
> 	    after:   "thumb_gen2";
> 	 }
> 	 program { name: "thumb_gen2";
> 	    action:  STATE_SET "min" 0.0;
> 	    target:  "icon";
> 	    after:   "thumb_gen3";
> 	 }
> 	 program { name: "thumb_gen3";
> 	    action:  STATE_SET "max" 0.0;
> 	    target:  "icon";
> 	    transition: DECELERATE 0.2;
> 	    after:   "thumb_gen4";
> 	 }
> 	 program { name: "thumb_gen4";
> 	    action:  STATE_SET "default" 0.0;
> 	    target:  "icon";
> 	    transition: SINUSOIDAL 0.1;
> 	    after:   "thumb_gen5";
> 	 }
> 	 program { name: "thumb_gen5";
> 	    action:  STATE_SET "max2" 0.0;
> 	    target:  "icon";
> 	    transition: SINUSOIDAL 0.2;
> 	    after:   "thumb_gen6";
> 	 }
> 	 program { name: "thumb_gen6";
> 	    action:  STATE_SET "default" 0.0;
> 	    target:  "icon";
> 	    transition: SINUSOIDAL 0.3;
> 	 }
>       }
>    }
> 
> _______________________________________________
> Openmoko community mailing list
> community at lists.openmoko.org
> http://lists.openmoko.org/mailman/listinfo/community
> 


-- 
------------- Codito, ergo sum - "I code, therefore I am" --------------
The Rasterman (Carsten Haitzler)    raster at rasterman.com





More information about the community mailing list