My ideas about GSOC Tiles project

Boudewijn Rempt boud at
Thu Mar 26 19:57:38 CET 2009

On Tuesday 24 March 2009, Dmitry Kazakov wrote:

> Maybe we are both right ;) The implementation should be spread between
> KisDataManager and KisPaintDevice. Now i've got how to describe that:
> We have to add a new layer of abstraction (not sure this term is right
> here) to these classes: that is "current zoom level". 

Yes, I think you are right at that. It is a bit of a pity, since I've tried to 
make krita/image as independent of any display considerations as possible, but 
I think it cannot be helped. It also means that the KisDataManager needs to 
know about the colorspace, so the scaling algorithms can work.
>        /**
>          * 2boud: Why this KisProjectionCache is needed at all? I guess if
> caching and zooming is done in Tiles, this class (and
> KisPrescaledProjection too) will be happily removed

Yes, quite probably. The cache exists because it's pretty slow to convert from 
KisImage to QImage (partly because we need to colour correct, partly because 
copying data is just plain slow). The prescaled projection class exists 
because scaling using a nice algorithm is very slow; in 1.6 we used nearest 
neighbour but that has the disadvantage that thin lines disappear at low zoom 
levels. See 
for the difference.

But mipmapping would obviate the need for these two way too complicated 

> Have i understood the architecture right?

Yes, quite correct.

> When we introduce "zoom levels", we'll be able to request from paintDevice
> any zoomed-version of original image. Speaking about caseA, the Tiles
> subsystem will know that only one tile changed and will scale it down.
> Resulting projection will consist of prescaled old tiles and the new one.
> Writing to the paintDevice by all the paintOps should always be done to
> 100% level, but reading at any level. There is only exception - previewing
> (see caseB). Preview mechanism will feed filters with scaled-down versions
> of image, stored in internal m_previewPaintDevice (or just checkout
> scaled-down version from paintDev. to m_previewQImage, that is issue for
> dispute).
> So, i see "zoom levels" like that:
>   Tiles subsystem                    KisTiledPaintDevice
> | ---------------- |                |--------------  |
> | *stores pyramids |<----some------>|   it's *only*  |
> | *caches tiles    |<-*!internal!*->|    inteface    |<-...External
> | *scales tiles    |<----links----->|    to tiles    |<-...interface
> | *etc...          |                |   subsystem    |
> |
> |                  |                | (with drawing, |
> *------------------*                |   of course)   |
>                                     *----------------*
> External interface should be smth like:
> *-
> |
> |--convertToQImageNew(zoomlevel_struct zoomlevel)
> |--drawSomething(zoomlevel_struct zoomlevel)
> |--...
> |
> |----------------
> | LEGACY PART (works only at 100% zoom)
> |
> |--convertToQImage()->
> |--drawSomething()->
> |--...
> *-
> struct zoomlevel_struct {
>     enum {
>         ORIGINAL=0,
>         NOT_ORIGINAL
>     } should_use_m_scale;
>     double m_scale;
> }
> In such a case algorithm for caseA will be much simplier and more
> efficient:
> 1) PaintOp changes a couple of pixels on some tile (scale 100%)
> 2) KisGroupLayer activates KisMergeVisitor, that in turn copies
> KisPaintLayer->d->m_paintDevice to ... to __root_layer->d_m_projection
>     This step is like in previous case, except of _all the operations are
> made in current zoom-level_ (disputable?) and prescaled-down tiles cached
> 3) Then KisQPainterCanvas::paintEvent comes, this function in turn:
>     a) calls KisImage::convertToQImage just copies
> __root_layer->d_m_projection (all the work is already done).
> 4) KisQPainterCanvas draws these two pixels =)

I'd like to have Bart Coppens' input, but it sounds good. 

> >
> > following Qt4 api
> > conventions.
> Where should i read about it?

Gosh... I'm not sure I can retrieve the link. Basically, Qt tries to get away 
from true/false flags in their api because they can be confusing and instead 
defines an enum so you can pass sensible, descriptive paramenters.

> Ideally we shouldn't compose layers at all, we should compose tiles, but i
> can't imagine how atm :)

That's complicated because tile boundaries are not necessarily congruous: that 
is, if a paint device is moved from 0,0, it's origin moves, the content of the 
tiles isn't moved.

> Something like Read-copy-update (RCU) in linux? I guess it's too weird for
> that.

I think it's the same idea -- copy-on-write and rcu. 

> What was the cause of this boost?

Less allocations -- we'd allocate a big tile pool once, and give every paint 
device tiles from this pool, instead of allocating a pool per paint device. 
Especially since we create and discard paint devices a whole lot in krita.

> Taking into account the parallel thread about full-time working. I have
> four exams at the university in the beginning of June, but i hope to manage
> to pass two of them in advance in May. So at least two of them are left for
> June and it'll take at least 9 days. Can it prevent me from GSOC?

That should be okay.

> PPS:
> /* in the beginning */
> heh.. let's sit down and write a short reply...
> =)

Boudewijn Rempt |

More information about the kimageshop mailing list