Re: [E-devel] Evas render rotation issues

2013-02-22 Thread The Rasterman
On Wed, 20 Feb 2013 17:10:29 + Daniel Willmann d.willm...@samsung.com
said:

 Hello raster and other evas gurus,
 
 last week we were confronted with memory usage peaks when rotating a
 canvas through elm_win_rotation_with_resize_set.
 
 We didn't really understand what was going on and so we came up with a
 patch which seemed to fix the problem:
 
 http://git.enlightenment.org/core/efl.git/commit/?id=139737247d563f53a064c7f4a025a89ed64c2983
 
 We now know that this fix was just stupid and doesn't really work (or
 fix anything). After some more digging into the render code we have
 learned so far (please correct any place where we're wrong):

looks so - either way u have to allocate temporary rgba image buffers to render
data into BEFORE its rotated out to the real upload buffer...

 * Only changed regions get rendered

correct. evas figures out update regions and evas render walks thru these
asking the engine for each... and then renders to eac, then pushes it back
when done leaving it up to the engine to rotate it to the putput and upload to
display when done (it gets deferred until flush for less artifacts).

 * For each region a new region_for_update is allocated with
   evas_software_xlib_outbuf_new_region_for_update()

correct.

 * The image returned by this function is updated with the image data
   for the region

correct. by the render code.

 * evas_software_xlib_outbuf_push_updated_region() takes care of any
   conversion (colorspace, rotation) that might be necessary

correct. it converts here and leaves in the shm buffer.

 * evas_software_xlib_outbuf_flush() sends the updated regions to X

correct.

 * After the rendering is done the stuff allocated through
   *outbuf_new_region_for_update is freed again

correct. :)

 In the common case (rotation is 0, display depth is 32bit):
 * outbuf_new_region_for_update() allocates an
   XShmImage and attaches its data directly to the evas_image data.

allocates and/or looks in its shm cache of existing shm segments, but correct.
this becomes a zero copy/convert path. it still is a copy up to display by x,
but within evas then no copies are done.

 * outbuf_push_updated_region() detects this case
   ( - if (data == (unsigned char *)src_data) ) and skips any convert
   function

correct. :)

 In any other case (i.e. rotation is 90, 180 or 270):
 * outbuf_new_region_for_update() allocates data for
   the evas_image. This is where the updates will get rendered into.
   It also allocates an XShmImage which is what will be pushed to X in
   outbuf_flush(). The dimensions of the XShmImage is transposed if
   the rotation is 90 or 270.

correct.

 * outbuf_push_updated_region() selects the appropriate conversion
   function and updates the XShmImage with the rotated image.

correct.

 What now happens if we rotate a large window is that the complete canvas
 needs to be redrawn - resulting in a large allocation of both the
 original image and the rotated XShmImage. After that initial large
 update we only have to update smaller regions so this is a one-time spike.

correct. though if u scroll a list filling most of the window.. it'll be
large regions too. at any point in time you need both the rendered data and its
converted/rotated output version (as at some point u have to do this
rotate/convert and both src and dest have to exist at once). evas just keeps
the whole set of them - and the whole set can in theory add up to a whole
window in size with both the unrotated/unconverted src and rotated/converted
output.

 The question is now how do we reduce the allocation peaks when rotating
 large windows? One possibility we see is breaking up the one large
 fullscreen update into smaller ones and rendering those sequentially.
 Does that make sense? Is there another/better way?

that leads to artifacts. it leads to SEEING the window update tile/region by
region. it also creates inefficiencies as you do the clipping and rendering of
many more smaller regions. you will pay a price in speed and artifacts. the set
is kept around and flushed in 1 go to minimize visible artifacts as x then
hopefully copies all the shm segments up in a very short timeframe as the
requests are temporally right next to eachother.

basically the answer is... you can't. not without creating other problems.

let me give you an extreme example:

you COULD cut down the buffer memory needed to just 1 pixel... if you update
the whole canvas 1 pixel at a time. technically evas itself allows for this. it
is, in theory, possible to make an engine that works this way. this is actually
similar to postscript printers from what i know, but they keep just 1 scanline
around at a time. they literally just keep a high resolution pixel buffer of
scaline and then scan that out with a laser (for inkjet i assume they keep
maybe 8, 16 or 32 lines depending on the head size). in this extreme example
set you now can render with very little buffer memory needed, BUT.. you pay
price in performance as you 

[E-devel] Evas render rotation issues

2013-02-20 Thread Daniel Willmann
Hello raster and other evas gurus,

last week we were confronted with memory usage peaks when rotating a
canvas through elm_win_rotation_with_resize_set.

We didn't really understand what was going on and so we came up with a
patch which seemed to fix the problem:

http://git.enlightenment.org/core/efl.git/commit/?id=139737247d563f53a064c7f4a025a89ed64c2983

We now know that this fix was just stupid and doesn't really work (or
fix anything). After some more digging into the render code we have
learned so far (please correct any place where we're wrong):

* Only changed regions get rendered
* For each region a new region_for_update is allocated with
  evas_software_xlib_outbuf_new_region_for_update()
* The image returned by this function is updated with the image data
  for the region
* evas_software_xlib_outbuf_push_updated_region() takes care of any
  conversion (colorspace, rotation) that might be necessary
* evas_software_xlib_outbuf_flush() sends the updated regions to X
* After the rendering is done the stuff allocated through
  *outbuf_new_region_for_update is freed again


In the common case (rotation is 0, display depth is 32bit):
* outbuf_new_region_for_update() allocates an
  XShmImage and attaches its data directly to the evas_image data.
* outbuf_push_updated_region() detects this case
  ( - if (data == (unsigned char *)src_data) ) and skips any convert
  function


In any other case (i.e. rotation is 90, 180 or 270):
* outbuf_new_region_for_update() allocates data for
  the evas_image. This is where the updates will get rendered into.
  It also allocates an XShmImage which is what will be pushed to X in
  outbuf_flush(). The dimensions of the XShmImage is transposed if
  the rotation is 90 or 270.
* outbuf_push_updated_region() selects the appropriate conversion
  function and updates the XShmImage with the rotated image.


What now happens if we rotate a large window is that the complete canvas
needs to be redrawn - resulting in a large allocation of both the
original image and the rotated XShmImage. After that initial large
update we only have to update smaller regions so this is a one-time spike.

The question is now how do we reduce the allocation peaks when rotating
large windows? One possibility we see is breaking up the one large
fullscreen update into smaller ones and rendering those sequentially.
Does that make sense? Is there another/better way?


Regards,
Stefan and Daniel

--
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_feb
___
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel