The code used for showing the image has been changed quite a bit recently. The
first modification was that addition of a mipmap pyramid implemented on the
tile level that acts as a foundation for more efficient redraws that no longer
needs to traverse all the data of the image at full resolution to redisplay it
when zoomed out. In 2.4rc1 yielding a performance increase (assuming that the
code does indeed cache results between levels correctly.)
For 2.4rc1 I added code that did something close to bilinear interpolation from
the next larger mipmap level, this yielded even better results at a slight
performance penalty. (There might also be a crasher bug introduced for some
image size/display size combinations, not fully sure about this though).
In current SVN I've committed code that implements a box-filter that uses a 3x3
neighborhood instead of the 2x2 neighborhood that the bilinear filter used,
there still are room for some improvements both to the code readability as well
as the performance of the re sampling.
For many common resolutions these changes should have no impact on the speed
compared to the plain pyramid (100%, 50%, 25%, since nearest neighbour
re sampling is used directly on the correct pyramid level). It is possible with
this implementation to enable anti aliasing between the rectangles representing
pixels at zoom levels > 100% using this code, I am not sure if this is desired
or not, I have thus left it without anti aliasing in these cases.
If others want to help clean up as well as optimize the code, the places to look
are in app/display/gimpdisplayshell-render.c
The innermost function is compute_sample() , this function should be modified
to be as fast as possible since it is the piece of code called most of the
time. The shifting being done is done to avoid some integer overflowing issues;
it would be nice if these issues could be resolved, there are also some other
comments about possible optimizations/reorganization of the code possible here
in comments within the function.
render_image_tile_fault() this function is a generic function implementing the
3x3 neighbourhood traversal needed for the box filter, this code should
probably focus on readability instead of performance since it will most of the
time be handing off the actual work to either render_image_tile_fault_nearest
or render_image_tile_fault_one_row, render_image_tile_fault_one_row() is the
image iteration and tile traversal code that is called for the most common case
(all pixels needed can be fetched from a single row of tiles.) Reducing the
overhead (number of tiles kept in memory, etc.) for this function will result
in a faster display.
A general optimization that hasn't been done yet on a more architectural level
would be moving the projection to use pre-multiplied alpha, this would remove
the premultiply and un-premulitply steps for each level of the pyramid
as well as
the scaled blit itself, thankfully when I start migrating this last piece of
box-filtering code back to GEGL again I already have that, and thus should be
able to do slightly faster scaled blitting from the pyramid.
/Øyvind K.