Discussion:
[Inkscape-devel] NEW: cairo rendering in outline mode
bulia byak
2007-02-17 02:51:25 UTC
Permalink
I was curious if cairo is in fact slower or faster than our current
renderer. I didn't feel like converting us totally to cairo yet, but
we have outline mode which is much simpler and perfect for tests like
this. So in about 3 hours (of which 2 hours were spent figuring out a
known bug in cairo) I converted our outline mode rendering to cairo.

The result of this experiment, after I adjusted the tolerance of cairo
to match our outline mode quality, is near parity. That is, cairo is
about as fast as our own renderer, at least for outline mode (i.e.
lots of paths but no gradients or transparency). However this claim
needs to be qualified:

- It is only true for the latest version of cairo (tested with
1.3.14). Versions 1.2.x are noticeably slower.

- This uses image backend to render to a memory buffer, and therefore
cannot use any hardware acceleration. Using hardware-accelerated
backends will require much more drastic changes in Inkscape's
architecture.

- Even with image backend, currently cairo is used _only_ for path
rendering, each path going to its own temp buffer, and these buffers
are later composed together just as they were before. I suspect that
if this is optimized by allowing a single cairo context draw all of
the paths in the drawing into a single buffer, performance will
improve noticeably.

In any case, since this does not make for any speed regression, and
since it fixes at least one bug that our native renderer had in
outline mode, I committed this. Please test outline mode thoroughly
and report if you find any problems. If everything works fine I'll
remove the old outline mode code and will look into doing some further
optimizations.
--
bulia byak
Inkscape. Draw Freely.
http://www.inkscape.org
Bryce Harrington
2007-02-17 06:53:51 UTC
Permalink
Post by bulia byak
I was curious if cairo is in fact slower or faster than our current
renderer. I didn't feel like converting us totally to cairo yet, but
we have outline mode which is much simpler and perfect for tests like
this. So in about 3 hours (of which 2 hours were spent figuring out a
known bug in cairo) I converted our outline mode rendering to cairo.
Excellent! This is good news, and I hope a first step towards moving
more of our code over.

Bryce
bulia byak
2007-03-04 03:51:34 UTC
Permalink
More news on Cairo. I did some slightly deeper rearchitecturing and
switched all of the drawing in outline mode to cairo (previously it
was only for shapes), making all objects draw into a common cairo
surface. Then I added a simple byte-reverser which converts the final
buffer from RGBA to ABGR for PPC Macs and other big-endian systems.
This had to be done only once per buffer render, so while Macs will
render a bit slower because of that, the difference should not be
significant. Jon Cruz reports that the byte-reverser works and outline
mode displays correctly on again on his Mac.

Approximately the same thing needs to be done for normal mode
rendering and then for all the canvas items (knots, handles, etc).
This is A LOT more work, of course. Gradients, patterns, clipping,
masking, filters - all of this holds innumerable surprises for an
intrepid cairoifier. The canvas items are especially fun because all
of them render into a 3-byte buffer (RGB without opacity, packed)
which has absolutely no counterpart in cairo, and most of them are
drawn by manual pixel-flipping via p += 3 pointers...

What mostly motivates me in this work is not speed gains (as I said,
they are modest), but the reduction in memory consumption - and it is
BIG. I loaded a complex drawing in outline mode in 0.45; top reported
222Mb total virtual memory. Then I loaded the same into current SVN -
118Mb, almost twice less! That's how bad our old renderer is. It not
only uses insane amounts of memory but also constantly leaks it (see
bug 1460453 for details). If we succeed in ditching the old renderer
for the normal mode too, Inkscape will officially stop being a memory
hog.

Update: Carl Worth has just told me that there are plans in cairo to
support more buffer formats in the near future. Along with the
bugfixes, this will make cairo much more attractive for us. Perhaps
the switch will not be so much pain after all.
--
bulia byak
Inkscape. Draw Freely.
http://www.inkscape.org
bulia byak
2007-02-17 15:51:29 UTC
Permalink
I soon realized that removing at least one intermediate buffer would
be easy, so I did it. As a result, outline mode is now about 25%
faster than in 0.45, which is quite noticeable.
--
bulia byak
Inkscape. Draw Freely.
http://www.inkscape.org
jiho
2007-02-25 01:16:03 UTC
Permalink
Post by bulia byak
In any case, since this does not make for any speed regression, and
since it fixes at least one bug that our native renderer had in
outline mode, I committed this. Please test outline mode thoroughly
and report if you find any problems. If everything works fine I'll
remove the old outline mode code and will look into doing some further
optimizations.
I have compiled SVN for the first time since 0.45 today and there
appear to be a problem with this new outline mode: nothing is visible
in outline mode, tough objects are still selectable.
This is with cairo @1.2.6, gtk2 @2.10.9 on Mac OS X. There are no
message to the startup terminal. Is there anyway I can get some more
useful information?

JiHO
bulia byak
2007-02-25 01:21:01 UTC
Permalink
Post by jiho
I have compiled SVN for the first time since 0.45 today and there
appear to be a problem with this new outline mode: nothing is visible
in outline mode, tough objects are still selectable.
Can you try a newer cairo, ideally 1.3.14?
--
bulia byak
Inkscape. Draw Freely.
http://www.inkscape.org
jiho
2007-02-25 01:41:43 UTC
Permalink
Post by bulia byak
Post by jiho
I have compiled SVN for the first time since 0.45 today and there
appear to be a problem with this new outline mode: nothing is visible
in outline mode, tough objects are still selectable.
Can you try a newer cairo, ideally 1.3.14?
Do you mean just fo testing or to use 1.3.14 in the future? If this
is for a test I can probably manage to do it. If it is for real worl
use I would prefer not to because:
- 1.2.6 is the stable release and 1.3.x is the unstable one
- it would mean not using a package distribution system to resolve
Inkscape dependencies which actually means more trouble for people
compiling Inkscape on OS X (unless we switch to Michael build script,
but then again, package distribution systems are precisely there to
avoid us some trouble in these respects). There are very few of us so
it can be seen as a minor annoyance but, in my point of view, it is
one more barrier to get _more_ people helping to compile and test
development versions of Inkscape on OS X.

JiHO
---
http://jo.irisson.free.fr/
bulia byak
2007-02-25 01:49:20 UTC
Permalink
Post by jiho
Post by bulia byak
Post by jiho
I have compiled SVN for the first time since 0.45 today and there
appear to be a problem with this new outline mode: nothing is visible
in outline mode, tough objects are still selectable.
Can you try a newer cairo, ideally 1.3.14?
Do you mean just fo testing or to use 1.3.14 in the future?
Well, of course, start by testing it out. If it doesn't work with
3.14, we'll need to look elsewhere for the problem. If it does, we'll
look into how we can move the Mac version to a newer cairo without
pain for anyone (perhaps just by waiting until it becomes stable and
supported).
--
bulia byak
Inkscape. Draw Freely.
http://www.inkscape.org
bulia byak
2007-02-25 16:10:16 UTC
Permalink
Last night, with the help of Carl Worth, the issue of cairo/inkscape
not working on mac was more or less clarified. Here's how I understand
it.

When drawing into a memory buffer, cairo uses a fixed byte order of
the R, G, B, A bytes regardless of the platform.

Inkscape and GDK (which is used by Inkscape for drawing to screen),
however, both use system-dependent byte order, i.e. the order of R, G,
B, A is determined by the hardware and is different on PC and Mac
platforms.

And it so happens that the fixed order of cairo coincides with the
hardware order on PC but not on Mac. Hence, painting by cairo directly
into Inkscape/GDK buffers worked on PC but on Mac, all colors are
wrong and (in case of outline) black color gets zero opacity, i.e.
becomes invisible.

Essentially, this means that Inkscape and cairo are not compatible as
is, and that a gradual switching of parts of our display engine to
cairo is not possible. (Unless we ditch Macs, of course.)

Even if we switch our screen output from using GDK to cairo (which is
relatively easy), this won't help - it will just break rendering on
PCs too. Inkscape has a lot (and I do mean A LOT) of code that assumes
system-dependent byte order. Composers, decomposers, premultipliers,
unpremultipliers, blitters and blotters of all sizes and colors
permeate the codebase. Most of them come all the way from Sodipodi.

Now, of course, it's possible to create "adapters" for cairo bits.
That is, every time we use cairo, instead of drawing directly into
Inkscape buffer, we can draw into a temporary buffer instead,
rearrange the bytes in that buffer, and then compose that into the
main buffer. But that is certain to more than negate the feeble speed
gains we're seeing from cairo's image backend rendering.

Or, we can attempt a much more drastic rearchitecturing, by changing
our functions so they pass around cairo contexts instead of Inkscape
buffers. With this approach, byte reordering will be needed less
frequently, and eventually eliminated completely. But this is not only
much more work, it will also mean a lot more bugs and regressions and
quite some time before Inkscape is usable again.

So, it looks like due to this stupid byte-order issue, cairo for us is
practically an all-or-nothing proposition - and much more hassle than
I expected. I'm not saying it's impossible but it is quite a major
project that cannot be done gradually.

Unless, of course, cairo gets so in love with Inkscape as to provide
us with a new image surface with system-dependent byte order...
Post by jiho
I have compiled SVN for the first time since 0.45 today and there
appear to be a problem with this new outline mode: nothing is visible
in outline mode, tough objects are still selectable.
--
bulia byak
Inkscape. Draw Freely.
http://www.inkscape.org
Aaron Spike
2007-02-25 17:01:51 UTC
Permalink
Post by bulia byak
So, it looks like due to this stupid byte-order issue, cairo for us is
practically an all-or-nothing proposition - and much more hassle than
I expected. I'm not saying it's impossible but it is quite a major
project that cannot be done gradually.
Is there enough developer support to do this in a non-gradual fashion?

Aaron Spike
bulia byak
2007-02-25 17:35:09 UTC
Permalink
Post by Aaron Spike
Post by bulia byak
So, it looks like due to this stupid byte-order issue, cairo for us is
practically an all-or-nothing proposition - and much more hassle than
I expected. I'm not saying it's impossible but it is quite a major
project that cannot be done gradually.
Is there enough developer support to do this in a non-gradual fashion?
That's what I was trying to measure by sending that email :)
--
bulia byak
Inkscape. Draw Freely.
http://www.inkscape.org
Bryce Harrington
2007-02-25 19:49:58 UTC
Permalink
Post by bulia byak
Post by Aaron Spike
Post by bulia byak
So, it looks like due to this stupid byte-order issue, cairo for us is
practically an all-or-nothing proposition - and much more hassle than
I expected. I'm not saying it's impossible but it is quite a major
project that cannot be done gradually.
Is there enough developer support to do this in a non-gradual fashion?
That's what I was trying to measure by sending that email :)
Well, how about this...

We'd been assuming previously that a cairo conversion was going to be a
major project already - it was only recently that we got hope that it
could be a quick switch. So we had been planning on focusing 0.46 on
prepatory refactoring, to get the codebase into a better shape where
all-or-nothing switches like cairo could be done a bit easier. With
your work there's now a better understanding of the specifics, so maybe
it'll be clearer where the refactoring is needed?

I haven't gotten much into the internals of the renderer, so don't know
much about how the RGBA ordering is handled (could you point out an
example?), but I do know what you mean about rendering code being
scattered all over the place.

An initial thought would be - could the RGBA-specific rendering code be
better compartmentalized? E.g., instead of being present in 30
different files, reducing that to 5 or 10?

Along with that, could the existing renderer calls be modified to be
exact analogs to the cairo calls, to the degree that we'd be able to
later just search and replace them with the corresponding cairo calls?

If this is not doable, another thought to incrementalize the mass change
would be to incorporate preprocessor macros, and a WITH_CAIRO configure
option, that allows us to put the new cairo code while still preserving
the old system for those who need to use it. Obviously this incurs some
ugliness in the short term.

Of course, a branch is another option. We've done this before, with
inkboard, gtkmm, and so on, and know it works. It also has some
downsides of re-integration hassles and the risk of not getting
sufficient developer attention when it's outside the codebase. However,
you *can* work much more swiftly on a branch where you can cause mass
breakage to get things converted over. The big price to pay for this
approach will be lots of new bugs (offset somewhat by other bugs that
will become obsoleted).

Bryce
bulia byak
2007-02-25 21:06:37 UTC
Permalink
Post by Bryce Harrington
We'd been assuming previously that a cairo conversion was going to be a
major project already - it was only recently that we got hope that it
could be a quick switch. So we had been planning on focusing 0.46 on
prepatory refactoring, to get the codebase into a better shape where
all-or-nothing switches like cairo could be done a bit easier.
Some of the preparatory work I already started doing, such as planning
to eliminate non-premultiplied mode (which cairo does not use, yet PNG
and on-screen icons must get non-premultiplied data).

Of course some other preparatory work may be needed. But mostly, it's
just grunt work. Someone needs to sit down and convert ALL the stuff.
As simple as that.

And the main problem is not that it's a lot of work. The main problem
is that all this must be done at once, otherwise it won't work. And
that means that the number of bugs after this conversion will be
bordering on unmanageable. Not only Inkscape bugs; cairo has its own
bugs, several of which I discovered already by the outline mode
exercise. They are all reported to cairo but I have no idea when they
will be fixed.

This cannot be done on the trunk because SVN must be usable for work
every day. And it does not seem to me that branches are a successful
strategy in general. Work in branches seems rather prone to dying out
soon after branching.

I'm also of the opinion that cairo could make this switch much easier
for us if they chose to. If only they could provide an image surface
which is not premultiplied and another which uses a byte order
compatible with ours on all platforms, most of our problems would be
eliminated and the switch could be done very gradually, with proper
community testing of every step.
Post by Bryce Harrington
If this is not doable, another thought to incrementalize the mass change
would be to incorporate preprocessor macros, and a WITH_CAIRO configure
option, that allows us to put the new cairo code while still preserving
the old system for those who need to use it. Obviously this incurs some
ugliness in the short term.
I guess this is what will be done in the short term, at least for the
outline mode to be usable on Macs.
--
bulia byak
Inkscape. Draw Freely.
http://www.inkscape.org
Jasper van de Gronde
2007-02-25 22:29:58 UTC
Permalink
Post by bulia byak
Post by Bryce Harrington
We'd been assuming previously that a cairo conversion was going to be a
major project already - it was only recently that we got hope that it
could be a quick switch. So we had been planning on focusing 0.46 on
prepatory refactoring, to get the codebase into a better shape where
all-or-nothing switches like cairo could be done a bit easier.
Some of the preparatory work I already started doing, such as planning
to eliminate non-premultiplied mode (which cairo does not use, yet PNG
and on-screen icons must get non-premultiplied data).
I would hate to see this go, as it can give nicer results in some cases
(it's at least one reason why export often looks better). Of course
there would be less need for it if it was possible to use 16bits per
color. And if it would be the only thing against Cairo, well, don't let
it stop you, but if it would be possible to keep this possibility with
Cairo, that would be fabulous.
Aaron Spike
2007-02-26 00:15:35 UTC
Permalink
Post by bulia byak
This cannot be done on the trunk because SVN must be usable for work
every day. And it does not seem to me that branches are a successful
strategy in general. Work in branches seems rather prone to dying out
soon after branching.
I don't think this is strictly true. Filters were done on a branch, and
that branch didn't die until it merged back to trunk. Branches can work,
but they need the support and energy of two or more coders and lots of
organization.
Post by bulia byak
I'm also of the opinion that cairo could make this switch much easier
for us if they chose to. If only they could provide an image surface
which is not premultiplied and another which uses a byte order
compatible with ours on all platforms, most of our problems would be
eliminated and the switch could be done very gradually, with proper
community testing of every step.
Asking Cairo to dirty their API to help us along seems like quite a
large request. What's stopping these things from being done on our side?

Aaron Spike
Bryce Harrington
2007-02-26 00:31:32 UTC
Permalink
Post by Aaron Spike
Post by bulia byak
This cannot be done on the trunk because SVN must be usable for work
every day. And it does not seem to me that branches are a successful
strategy in general. Work in branches seems rather prone to dying out
soon after branching.
I don't think this is strictly true. Filters were done on a branch, and
that branch didn't die until it merged back to trunk. Branches can work,
but they need the support and energy of two or more coders and lots of
organization.
Same with the gtkmm branch - it also got to the point of reintegration
with the main codebase. In fact, interest died down only after
switching to a refactoring approach.

You could argue that if the work is prone to die out if it's done in a
branch, then perhaps there wasn't really sufficient interest in it to
begin with. Who's to say that same work wouldn't also die if done in
the main codebase. And with a branch if the work fails to reach the
point where it can be merged, then at least it isn't going to clutter
up the main codebase.
bulia byak
2007-02-26 00:41:15 UTC
Permalink
Post by Aaron Spike
Asking Cairo to dirty their API to help us along seems like quite a
large request.
As I understand it, GDK uses the same fixed order as Inkscape.
Providing a mode compatible with this very widely used lib, to
facilitate migration from it, does not sound like "dirtying" to me.
Post by Aaron Spike
What's stopping these things from being done on our side?
Nothing, except all the hassle with all-or-nothing conversion which I
tried to explain in this thread.
--
bulia byak
Inkscape. Draw Freely.
http://www.inkscape.org
jiho
2007-02-25 17:41:48 UTC
Permalink
first: wow I did not expect such a deep problem when reporting this.
I am glad you found it (I was about to repart that my new tests, with
Cairo 1.3.14 as you advised, presented the same problem, obviously...)
Post by bulia byak
Last night, with the help of Carl Worth, the issue of cairo/inkscape
not working on mac was more or less clarified. Here's how I understand
it.
When drawing into a memory buffer, cairo uses a fixed byte order of
the R, G, B, A bytes regardless of the platform.
Inkscape and GDK (which is used by Inkscape for drawing to screen),
however, both use system-dependent byte order, i.e. the order of R, G,
B, A is determined by the hardware and is different on PC and Mac
platforms.
And it so happens that the fixed order of cairo coincides with the
hardware order on PC but not on Mac. Hence, painting by cairo directly
into Inkscape/GDK buffers worked on PC but on Mac, all colors are
wrong and (in case of outline) black color gets zero opacity, i.e.
becomes invisible.
Is this a problem in the hardware in terms of the physical pieces in
the computer or in the way the hardware is handled by the system,
deeply inside? I don't know if this is relevant but then, is there a
difference between PowerPC and Intel based Macs (I am on a PPC)?
Indeed those new Macs are really more like PCs inside and the
difference with PCs is more and more at the system level. In which
case the future looks brighter because PPC macs will progresively
disappear. Meanwhile the old code would be conserved and wraped under
a configure option (like --with-old-rendering) we would use only on
PPC macs while Cairoification continues on the rest.
Post by bulia byak
Essentially, this means that Inkscape and cairo are not compatible as
is, and that a gradual switching of parts of our display engine to
cairo is not possible. (Unless we ditch Macs, of course.)
I hope this won't be the case! Notify me, I'll buy a PC then ;-)
Post by bulia byak
[...]
Thank you again for your efficient investigation. Too bad it yielded
such a result. I think it deserves a news item on the website though.

JiHO
---
http://jo.irisson.free.fr/
Michael Wybrow
2007-02-26 03:26:25 UTC
Permalink
Post by jiho
Post by bulia byak
And it so happens that the fixed order of cairo coincides with the
hardware order on PC but not on Mac. Hence, painting by cairo directly
into Inkscape/GDK buffers worked on PC but on Mac, all colors are
wrong and (in case of outline) black color gets zero opacity, i.e.
becomes invisible.
Is this a problem in the hardware in terms of the physical pieces in
the computer or in the way the hardware is handled by the system,
deeply inside? I don't know if this is relevant but then, is there a
difference between PowerPC and Intel based Macs (I am on a PPC)?
Hardware. PPC is big-endian, i386 is little-endian. So yes, the Intel
based Macs are little-endian, just like normal PCs and the new cairo
outline code works fine.


Cheers,
Michael
jiho
2007-02-26 08:17:03 UTC
Permalink
Post by Michael Wybrow
Post by jiho
Post by bulia byak
And it so happens that the fixed order of cairo coincides with the
hardware order on PC but not on Mac. Hence, painting by cairo directly
into Inkscape/GDK buffers worked on PC but on Mac, all colors are
wrong and (in case of outline) black color gets zero opacity, i.e.
becomes invisible.
Is this a problem in the hardware in terms of the physical pieces in
the computer or in the way the hardware is handled by the system,
deeply inside? I don't know if this is relevant but then, is there a
difference between PowerPC and Intel based Macs (I am on a PPC)?
Hardware. PPC is big-endian, i386 is little-endian. So yes, the
Intel based Macs are little-endian, just like normal PCs and the
new cairo outline code works fine.
So the future looks indeed brighter! Are there other big-endian
machines out there which could be problematic?
Unless there is a concern with the fact that hardware order and fixed
order are coinciding *by chance alone* on little-endian machines,
work may continue as planned while keeping the old code inside ifdefs
and having a configure option for big-endian machines for a little
while (or even an automatic switch turned on when configure detects
that the machine is big-endian). Indeed, PPC machines will probably
disappear quite fast, the Mac community being usually a early-
adopting one. For example, many software makers already announce that
the next version of their software will only run on version 10.5 of
the OS (the next version to come) which is a paid upgrade from 10.4
and will be out only one year after 10.4... and no one seems to have
concerns with this (well, appart from me that is ;-) ). Therefore
Inkscape won't be too much of a bad guy if versions 0.45 or 0.46 were
the last to be PPC compatible.
Plus, I think I am the only one here left with a PPC machine and will
probably ditch it soon for a new i386 one. Whatever I do, I will have
less and less time over the next 6 months (because of the end of my
PhD). Hence, unless someone else compiles svn snapshots with a PPC
machine, any new code probably won't have much testing on this
platform (while keeping old code there will be less of a problem).

Just my humble opinion on a matter that overwhelms me...

JiHO
---
http://jo.irisson.free.fr/
Jon A. Cruz
2007-02-26 08:37:10 UTC
Permalink
Post by jiho
Indeed, PPC machines will probably
disappear quite fast, the Mac community being usually a early-
adopting one. For example, many software makers already announce that
the next version of their software will only run on version 10.5 of
the OS (the next version to come) which is a paid upgrade from 10.4
and will be out only one year after 10.4... and no one seems to have
concerns with this (well, appart from me that is ;-) )
Well, I wouldn't go that far.

In fact, the Mac community also tends to *really* hang onto older
hardware. Resale value of older macs seems to be higher than one
could account for on pure technical abilities. And the only reason
I've left my old G4 behind for this G5 is that the G4 got killed in
our house fire. :-)

Another factor countering the 10.5 point is that a much higher
percentage of mac owners do buy the OS upgrades. So unlike MS
systems, a vendor supporting 10.5 can expect to get a lot of owners
with older hardware. I forget off-hand where the last details were,
but I just read an article about that in the last week or so.
bulia byak
2007-02-26 15:56:11 UTC
Permalink
So the next questions is, do we have an ifdef that filters out only
PPC-based Macs? If not, can the autoconfig gurus please help with
creating one?
--
bulia byak
Inkscape. Draw Freely.
http://www.inkscape.org
Jon A. Cruz
2007-02-26 17:04:27 UTC
Permalink
Post by bulia byak
So the next questions is, do we have an ifdef that filters out only
PPC-based Macs? If not, can the autoconfig gurus please help with
creating one?
We might want to try to hit all big-endian machines, since it sounds
like it's purely an endianess problem.
Bryce Harrington
2007-02-26 18:20:59 UTC
Permalink
Post by Jon A. Cruz
Post by bulia byak
So the next questions is, do we have an ifdef that filters out only
PPC-based Macs? If not, can the autoconfig gurus please help with
creating one?
We might want to try to hit all big-endian machines, since it sounds
like it's purely an endianess problem.
Curiously, there's a third endianness listed in endian.h:

#define __LITTLE_ENDIAN 1234
#define __BIG_ENDIAN 4321
#define __PDP_ENDIAN 3412

Bryce
MenTaLguY
2007-02-26 19:27:49 UTC
Permalink
Post by Bryce Harrington
#define __LITTLE_ENDIAN 1234
#define __BIG_ENDIAN 4321
#define __PDP_ENDIAN 3412
Thankfully, PDP-endianness is not an issue on any platforms we target.

-mental
Michael Wybrow
2007-02-26 21:36:51 UTC
Permalink
Post by Jon A. Cruz
Post by bulia byak
So the next questions is, do we have an ifdef that filters out only
PPC-based Macs? If not, can the autoconfig gurus please help with
creating one?
We might want to try to hit all big-endian machines, since it sounds
like it's purely an endianess problem.
Glib gives you this information: you can just test for
G_BYTE_ORDER == G_BIG_ENDIAN


Cheers,
Michael
MenTaLguY
2007-02-26 21:59:51 UTC
Permalink
Post by Michael Wybrow
Glib gives you this information: you can just test for
G_BYTE_ORDER == G_BIG_ENDIAN
Let's use the glib version of these macros, then.

-mental
Ted Gould
2007-02-26 17:13:15 UTC
Permalink
Post by bulia byak
So the next questions is, do we have an ifdef that filters out only
PPC-based Macs? If not, can the autoconfig gurus please help with
creating one?
But, I guess the real question is: what does GDK do? If GDK doesn't
switch based on endian-ness, I think we'll be doing some pretty crazy
adjustments to work within the GDK framework.

--Ted
Bryce Harrington
2007-02-26 18:16:15 UTC
Permalink
Post by bulia byak
So the next questions is, do we have an ifdef that filters out only
PPC-based Macs? If not, can the autoconfig gurus please help with
creating one?
Is endian.h available on all platforms? This works on Ubuntu:


#include <endian.h>
#include <stdio.h>

int main() {
#ifdef BIG_ENDIAN
printf("This is a big endian machine\n");
#elif LITTLE_ENDIAN
printf("This is a little endian machine\n");
#else
printf("Neither BIG_ENDIAN nor LITTLE_ENDIAN are defined\n");
#endif
return 0;
}

Bryce
Bryce Harrington
2007-02-26 18:18:58 UTC
Permalink
Post by bulia byak
So the next questions is, do we have an ifdef that filters out only
PPC-based Macs? If not, can the autoconfig gurus please help with
creating one?
Whoops, I misunderstood the defines in endian.h. Here's a correction:

#include <endian.h>
#include <stdio.h>

int main() {
#if __BYTE_ORDER == __BIG_ENDIAN
printf("This is a big endian machine\n");
#elif __BYTE_ORDER == __LITTLE_ENDIAN
printf("This is a little endian machine\n");
#else
printf("Don't know the endianness of this machine\n");
#endif
return 0;
}
Bob Jamison
2007-02-26 22:29:18 UTC
Permalink
Post by bulia byak
So the next questions is, do we have an ifdef that filters out only
PPC-based Macs? If not, can the autoconfig gurus please help with
creating one?
How about a live test? Have an test like endian_type()
that returns BIG_ENDIAN or LITTLE_ENDIAN.

If this is too much of a burden at runtime, then add it
as a test during config time.

A good way to check is to look at the header of a Java .class file
in a hex editor.
Check out the magic number 0xcafebabe as bytes, then words.


Simple test:
1. Set a 32-bit int to some literal like 0x11223344;
2: Test byte[0]. If it is 0x11, it is BIG_ENDIAN,
if 0x44, it is LITTLE_ENDIAN.


But is value-shifting really that expensive? Assume
a canonical format for ARGB or RGBA, always in
the same byte order. Shift and mask to get the fields.
A bit more work, but infinitely more portable.


A = (pixel >> 24) & 0xff;
R = (pixel >> 16) & 0xff;
G = (pixel >> 8) & 0xff;
B = (pixel ) & 0xff;




bob
MenTaLguY
2007-02-26 22:39:46 UTC
Permalink
Post by Bob Jamison
How about a live test? Have an test like endian_type()
that returns BIG_ENDIAN or LITTLE_ENDIAN.
Um, no.

This is something that can and should be entirely accomodated at compile-time, as it's a feature of the compiler's target architecture.

-mental
Craig Bradney
2007-02-26 22:58:02 UTC
Permalink
Post by MenTaLguY
Post by Bob Jamison
How about a live test? Have an test like endian_type()
that returns BIG_ENDIAN or LITTLE_ENDIAN.
Um, no.
This is something that can and should be entirely accomodated at
compile-time, as it's a feature of the compiler's target architecture.
For the cmakers...
INCLUDE (${CMAKE_ROOT}/Modules/TestBigEndian.cmake)
TEST_BIG_ENDIAN(WORDS_BIGENDIAN)

Craig
Ted Gould
2007-02-26 17:11:53 UTC
Permalink
Post by jiho
So the future looks indeed brighter! Are there other big-endian
machines out there which could be problematic?
Yes. x86 is the only little-endian architecture that I know of. Well,
there's MIPS, but everyone I know of runs it in big-endian mode.

--Ted
Niko Kiirala
2007-02-25 18:42:39 UTC
Permalink
Sun, 25 Feb 2007 11:10:16 -0500
Post by bulia byak
When drawing into a memory buffer, cairo uses a fixed byte order of
the R, G, B, A bytes regardless of the platform.
Inkscape and GDK (which is used by Inkscape for drawing to screen),
however, both use system-dependent byte order, i.e. the order of R, G,
B, A is determined by the hardware and is different on PC and Mac
platforms.
Umh, ok... So this means, that NRPixBlocks have different byte orders
depending on system?

Is it just that, that colours are somewhere handled as 32-bit integers
and as such, the platform byte order (high endian / low endian) makes a
difference? Or is there some still deeper problem here?

And further, how do I properly determine the byte order for rgba
images? I am now coding the support for the feBlend filter, and for
that it is really important to know, from which byte to read the opacity
value ;)

(Also, this really should be documented. As the mode for rgba images is
called NR_PIXBLOCK_MODE_R8G8B8A8P, I've always assumed, that the format
is R8 G8 B8 A8)
--
Niko Kiirala
***@kiirala.com
http://niko.kiirala.com/
bulia byak
2007-02-25 20:22:52 UTC
Permalink
Post by Niko Kiirala
Umh, ok... So this means, that NRPixBlocks have different byte orders
depending on system?
Yes, looks like it.
Post by Niko Kiirala
Is it just that, that colours are somewhere handled as 32-bit integers
and as such, the platform byte order (high endian / low endian) makes a
difference? Or is there some still deeper problem here?
As I understand it, the difference is that Inkscape code reads/writes
the 4-byte value by individual components, i.e. as char values to
char* pointers. Cairo always does it as uint32 values to uint32*
pointers. And these two methods give different results on a Mac.

So, perhaps a more correct description is that, on the contrary, it's
Inkscape that always uses the fixed order of r, g, b, and a bytes.
Cairo on the other hand relies on uint32 values, and these get written
with different byte order depending on endianness of the plarform.
Perhaps some cairo expert can chime in to confirm or deny this.

Sorry for the confused explanations. I've never dreamt of being an
expert on these ugly topics :)
Post by Niko Kiirala
And further, how do I properly determine the byte order for rgba
images? I am now coding the support for the feBlend filter, and for
that it is really important to know, from which byte to read the opacity
value ;)
I think that so long as you do this by getting individual chars and so
long as it works on one platform, it will work everywhere, as our
entire codebase confirms. Problems start only when you try to mix in
cairo with its uint32s.
Post by Niko Kiirala
(Also, this really should be documented. As the mode for rgba images is
called NR_PIXBLOCK_MODE_R8G8B8A8P, I've always assumed, that the format
is R8 G8 B8 A8)
Yes, I think that's a correct assumption.
--
bulia byak
Inkscape. Draw Freely.
http://www.inkscape.org
Jasper van de Gronde
2007-02-25 22:24:32 UTC
Permalink
Post by bulia byak
...
So, perhaps a more correct description is that, on the contrary, it's
Inkscape that always uses the fixed order of r, g, b, and a bytes.
Cairo on the other hand relies on uint32 values, and these get written
with different byte order depending on endianness of the plarform.
Perhaps some cairo expert can chime in to confirm or deny this.
If that is the case you can ignore my earlier remark about my patch, as
it would then be correct in its assumption that the alpha channel is the
last byte in a pixel (if there is an alpha channel).
Post by bulia byak
Post by Niko Kiirala
(Also, this really should be documented. As the mode for rgba images is
called NR_PIXBLOCK_MODE_R8G8B8A8P, I've always assumed, that the format
is R8 G8 B8 A8)
Yes, I think that's a correct assumption.
Now you mention it, that is indeed how nr-compose.cpp handles the
components, so I guess that more or less settles it (otherwise there
would be rendering bugs pretty much all over the place).
Jon A. Cruz
2007-02-25 22:34:29 UTC
Permalink
Post by bulia byak
Post by Niko Kiirala
Is it just that, that colours are somewhere handled as 32-bit
integers
and as such, the platform byte order (high endian / low endian) makes a
difference? Or is there some still deeper problem here?
As I understand it, the difference is that Inkscape code reads/writes
the 4-byte value by individual components, i.e. as char values to
char* pointers. Cairo always does it as uint32 values to uint32*
pointers. And these two methods give different results on a Mac.
There is another *very* helpful tool for managing conversions and such.

LittleCMS does buffer conversion in its transform code. A list can be
seen in the tutorial:

http://www.littlecms.com/tutorial.txt

The include file "lcms.h" has more.

Anyway, an lcms transformation could be used to achieve the buffer
conversions. I would also assume that such transformations that are
commonplace would be fairly optimized already. Calling
cmsCreateTransform() with the stock sRGB profile for both input and
output and the proper two buffer types.

Of course... I would *love* to see this go in at the final step
before image data hits the screen. That is the best place for a color
management transform, and thus the call could serve two functions at
once.
bulia byak
2007-02-25 23:07:08 UTC
Permalink
Of course... I would *love* to see this go in at the final step before image
data hits the screen. That is the best place for a color management
transform, and thus the call could serve two functions at once.
Sounds like a good idea, although it will only solve a small part of
our problems. The main problem, summarizing, is that we have a lot of
pieces of code that render to buffers, and they all assume
Inkscape-style buffers. Changing them to cairo piece-by-piece, as I
initially hoped, is therefore impossible.
--
bulia byak
Inkscape. Draw Freely.
http://www.inkscape.org
Jasper van de Gronde
2007-02-25 22:17:02 UTC
Permalink
Post by bulia byak
Last night, with the help of Carl Worth, the issue of cairo/inkscape
not working on mac was more or less clarified. Here's how I understand
it.
When drawing into a memory buffer, cairo uses a fixed byte order of
the R, G, B, A bytes regardless of the platform.
Inkscape and GDK (which is used by Inkscape for drawing to screen),
however, both use system-dependent byte order, i.e. the order of R, G,
B, A is determined by the hardware and is different on PC and Mac
platforms.
This might cause a problem with a patch I just wrote, as it assumes the
alpha channel is the last byte (when using premultiplied alpha,
otherwise it doesn't matter), and I imagine there might other places too
which assume something about this order. So it might be a good idea to
do a thorough overhaul of the code anyway, to make sure everyone is on
the same page.

BTW, I would appreciate any pointers on how to properly test for this
case without having to do something like cast an array of four bytes to
a 32bit integer.
Jasper van de Gronde
2007-02-25 22:19:28 UTC
Permalink
Post by bulia byak
...
Or, we can attempt a much more drastic rearchitecturing, by changing
our functions so they pass around cairo contexts instead of Inkscape
buffers. With this approach, byte reordering will be needed less
frequently, and eventually eliminated completely. But this is not only
much more work, it will also mean a lot more bugs and regressions and
quite some time before Inkscape is usable again.
BTW, if you're looking for manpower to help with this, I wouldn't mind
helping out, but I'm pretty swamped the next two months (until the end
of april). After that I'd be willing to put a reasonable amount of time
into it.
bulia byak
2007-02-25 23:01:50 UTC
Permalink
Here's a message from a cairo developer - not sure if it reached our
list, so I'm forwarding it. It confirms that my initial description
was indeed incorrect: Inkscape uses fixed order, while Cairo's order
depends on platform. Sorry for the confusion (though it amounts to the
same thing from compatibility viewpoint).

---------- Forwarded message ----------
From: Jeff Muizelaar <***@infidigm.net>
Date: Feb 25, 2007 5:15 PM
Subject: Re: [cairo] Re: [Inkscape-devel] NEW: cairo rendering in outline mode
Post by bulia byak
Last night, with the help of Carl Worth, the issue of cairo/inkscape
not working on mac was more or less clarified. Here's how I understand
it.
When drawing into a memory buffer, cairo uses a fixed byte order of
the R, G, B, A bytes regardless of the platform.
This is incorrect. Cairo's byte order depends on the platform. See, for
example, pixman/src/fbpict.c:fbOver():

static CARD32
fbOver (CARD32 x, CARD32 y)
{
CARD16 a = ~x >> 24;
CARD16 t;
CARD32 m,n,o,p;

m = FbOverU(x,y,0,a,t);
n = FbOverU(x,y,8,a,t);
o = FbOverU(x,y,16,a,t);
p = FbOverU(x,y,24,a,t);
return m|n|o|p;
}

As is shown, the alpha component is always in the most significant byte. So
byte 0 on big endian and byte 3 on little endian.

However, Inkscape's code assumes a fixed byte order (see below). i.e R is byte
0, G is byte 1 etc.

void
nr_R8G8B8A8_N_EMPTY_A8_RGBA32 (unsigned char *px, int w, int h, int
rs, const unsigned char *mpx, int mrs, unsigned long rgba)
{
unsigned int r, g, b, a;
unsigned int x, y;

r = NR_RGBA32_R (rgba);
g = NR_RGBA32_G (rgba);
b = NR_RGBA32_B (rgba);
a = NR_RGBA32_A (rgba);

for (y = h; y > 0; y--) {
if (a == 0) {
memset(px, 0, w*4);
} else {
unsigned char *d = px;
const unsigned char *m = mpx;
for (x = w; x > 0; x--) {
d[0] = r;
d[1] = g;
d[2] = b;
d[3] = NR_PREMUL_111 (m[0], a);
d += 4;
m += 1;
}
}
px += rs;
mpx += mrs;
}
}
Post by bulia byak
Inkscape and GDK (which is used by Inkscape for drawing to screen),
however, both use system-dependent byte order, i.e. the order of R, G,
B, A is determined by the hardware and is different on PC and Mac
platforms.
And it so happens that the fixed order of cairo coincides with the
hardware order on PC but not on Mac. Hence, painting by cairo directly
into Inkscape/GDK buffers worked on PC but on Mac, all colors are
wrong and (in case of outline) black color gets zero opacity, i.e.
becomes invisible.
Essentially, this means that Inkscape and cairo are not compatible as
is, and that a gradual switching of parts of our display engine to
cairo is not possible. (Unless we ditch Macs, of course.)
Even if we switch our screen output from using GDK to cairo (which is
relatively easy), this won't help - it will just break rendering on
PCs too. Inkscape has a lot (and I do mean A LOT) of code that assumes
system-dependent byte order. Composers, decomposers, premultipliers,
unpremultipliers, blitters and blotters of all sizes and colors
permeate the codebase. Most of them come all the way from Sodipodi.
Fortunately, cairo has a lot of equivalent code that matches cairo's byte
order. It also looks like alot of inkscape's compositing code, like cairo's,
isn't particularily fast either.
Post by bulia byak
Now, of course, it's possible to create "adapters" for cairo bits.
That is, every time we use cairo, instead of drawing directly into
Inkscape buffer, we can draw into a temporary buffer instead,
rearrange the bytes in that buffer, and then compose that into the
main buffer. But that is certain to more than negate the feeble speed
gains we're seeing from cairo's image backend rendering.
Or, we can attempt a much more drastic rearchitecturing, by changing
our functions so they pass around cairo contexts instead of Inkscape
buffers. With this approach, byte reordering will be needed less
frequently, and eventually eliminated completely. But this is not only
much more work, it will also mean a lot more bugs and regressions and
quite some time before Inkscape is usable again.
So, it looks like due to this stupid byte-order issue, cairo for us is
practically an all-or-nothing proposition - and much more hassle than
I expected. I'm not saying it's impossible but it is quite a major
project that cannot be done gradually.
Unless, of course, cairo gets so in love with Inkscape as to provide
us with a new image surface with system-dependent byte order...
This is painful as well. All of cairo's software compositing routines use the
cairo byte order, and likewise X assumes this byte order as well.

-Jeff
--
bulia byak
Inkscape. Draw Freely.
http://www.inkscape.org
Bryce Harrington
2007-02-25 23:34:06 UTC
Permalink
Post by bulia byak
Here's a message from a cairo developer - not sure if it reached our
list, so I'm forwarding it. It confirms that my initial description
was indeed incorrect: Inkscape uses fixed order, while Cairo's order
depends on platform. Sorry for the confusion (though it amounts to the
same thing from compatibility viewpoint).
However, Inkscape's code assumes a fixed byte order (see below). i.e R is byte
0, G is byte 1 etc.
r = NR_RGBA32_R (rgba);
g = NR_RGBA32_G (rgba);
b = NR_RGBA32_B (rgba);
a = NR_RGBA32_A (rgba);
These macros along with a lot of others that appear to do similar rgba
operations are in nr-pixops.h. Perhaps a starting point would be to put
#ifdefs around them and provide cairo-compatible versions of each, if
some define is specified.
Post by bulia byak
for (y = h; y > 0; y--) {
if (a == 0) {
memset(px, 0, w*4);
} else {
unsigned char *d = px;
const unsigned char *m = mpx;
for (x = w; x > 0; x--) {
d[0] = r;
d[1] = g;
d[2] = b;
d[3] = NR_PREMUL_111 (m[0], a);
Next would be to find all the places where byte-order dependent
operations are being done, and add new macros in nr-pixops.h or some
other central place for those things that allow them to be ifdef'd as
well.

Bryce
Emanuele Aina
2007-02-26 15:01:10 UTC
Permalink
Post by bulia byak
So, it looks like due to this stupid byte-order issue, cairo for us is
practically an all-or-nothing proposition - and much more hassle than
I expected. I'm not saying it's impossible but it is quite a major
project that cannot be done gradually.
Unless, of course, cairo gets so in love with Inkscape as to provide
us with a new image surface with system-dependent byte order...
It should be possible to write a custom image surface which does this in
the inkscape codebase without putting it in the cairo library, thus
allowing the gradual shift to cairo.

In the worst case we can copy the image backend changing the byte order
of the surfaces and use this until the transition is completed, then
switching to the official image backend.
--
Buongiorno.
Complimenti per l'ottima scelta.
Bob Jamison
2007-02-25 09:45:06 UTC
Permalink
Post by jiho
- 1.2.6 is the stable release and 1.3.x is the unstable one
- it would mean not using a package distribution system to resolve
Inkscape dependencies which actually means more trouble for people
compiling Inkscape on OS X (unless we switch to Michael build script,
but then again, package distribution systems are precisely there to
avoid us some trouble in these respects). There are very few of us so
it can be seen as a minor annoyance but, in my point of view, it is
one more barrier to get _more_ people helping to compile and test
development versions of Inkscape on OS X
Inkscape is still <1.0, so trying new things is something that we must do.
We really don't even have a version yet.

We only need to think about stability after we have a 1.0+ baseline.
The next release will be extra special, because we are going to start
worrying
about an Inkscape API. How about that? Talk about scary! :-)

Our synchronicity with Cairo is a wonderful thing. We can weed out
all of the minuses and share the pluses and help to make each other the
best agents in our domains.



bob
jiho
2007-02-25 23:01:15 UTC
Permalink
Forward of a message by Jeff Muizelaar who is probably someone at
Cairo and could not post this to the list because he is not subscribed.
Date: 2007 February 25 22:15:09 CEST
Subject: Re: [cairo] Re: [Inkscape-devel] NEW: cairo rendering in
outline mode
Post by bulia byak
Last night, with the help of Carl Worth, the issue of cairo/inkscape
not working on mac was more or less clarified. Here's how I
understand
it.
When drawing into a memory buffer, cairo uses a fixed byte order of
the R, G, B, A bytes regardless of the platform.
This is incorrect. Cairo's byte order depends on the platform. See,
for
static CARD32
fbOver (CARD32 x, CARD32 y)
{
CARD16 a = ~x >> 24;
CARD16 t;
CARD32 m,n,o,p;
m = FbOverU(x,y,0,a,t);
n = FbOverU(x,y,8,a,t);
o = FbOverU(x,y,16,a,t);
p = FbOverU(x,y,24,a,t);
return m|n|o|p;
}
As is shown, the alpha component is always in the most significant
byte. So
byte 0 on big endian and byte 3 on little endian.
However, Inkscape's code assumes a fixed byte order (see below).
i.e R is byte
0, G is byte 1 etc.
void
nr_R8G8B8A8_N_EMPTY_A8_RGBA32 (unsigned char *px, int w, int h, int
rs, const unsigned char *mpx, int mrs, unsigned long rgba)
{
unsigned int r, g, b, a;
unsigned int x, y;
r = NR_RGBA32_R (rgba);
g = NR_RGBA32_G (rgba);
b = NR_RGBA32_B (rgba);
a = NR_RGBA32_A (rgba);
for (y = h; y > 0; y--) {
if (a == 0) {
memset(px, 0, w*4);
} else {
unsigned char *d = px;
const unsigned char *m = mpx;
for (x = w; x > 0; x--) {
d[0] = r;
d[1] = g;
d[2] = b;
d[3] = NR_PREMUL_111 (m[0], a);
d += 4;
m += 1;
}
}
px += rs;
mpx += mrs;
}
}
Post by bulia byak
Inkscape and GDK (which is used by Inkscape for drawing to screen),
however, both use system-dependent byte order, i.e. the order of
R, G,
B, A is determined by the hardware and is different on PC and Mac
platforms.
And it so happens that the fixed order of cairo coincides with the
hardware order on PC but not on Mac. Hence, painting by cairo
directly
into Inkscape/GDK buffers worked on PC but on Mac, all colors are
wrong and (in case of outline) black color gets zero opacity, i.e.
becomes invisible.
Essentially, this means that Inkscape and cairo are not compatible as
is, and that a gradual switching of parts of our display engine to
cairo is not possible. (Unless we ditch Macs, of course.)
Even if we switch our screen output from using GDK to cairo (which is
relatively easy), this won't help - it will just break rendering on
PCs too. Inkscape has a lot (and I do mean A LOT) of code that
assumes
system-dependent byte order. Composers, decomposers, premultipliers,
unpremultipliers, blitters and blotters of all sizes and colors
permeate the codebase. Most of them come all the way from Sodipodi.
Fortunately, cairo has a lot of equivalent code that matches
cairo's byte
order. It also looks like alot of inkscape's compositing code, like
cairo's,
isn't particularily fast either.
Post by bulia byak
Now, of course, it's possible to create "adapters" for cairo bits.
That is, every time we use cairo, instead of drawing directly into
Inkscape buffer, we can draw into a temporary buffer instead,
rearrange the bytes in that buffer, and then compose that into the
main buffer. But that is certain to more than negate the feeble speed
gains we're seeing from cairo's image backend rendering.
Or, we can attempt a much more drastic rearchitecturing, by changing
our functions so they pass around cairo contexts instead of Inkscape
buffers. With this approach, byte reordering will be needed less
frequently, and eventually eliminated completely. But this is not
only
much more work, it will also mean a lot more bugs and regressions and
quite some time before Inkscape is usable again.
So, it looks like due to this stupid byte-order issue, cairo for
us is
practically an all-or-nothing proposition - and much more hassle than
I expected. I'm not saying it's impossible but it is quite a major
project that cannot be done gradually.
Unless, of course, cairo gets so in love with Inkscape as to provide
us with a new image surface with system-dependent byte order...
This is painful as well. All of cairo's software compositing
routines use the
cairo byte order, and likewise X assumes this byte order as well.
JiHO
---
http://jo.irisson.free.fr/
Loading...