[OpenJDK 2D-Dev] sun.java2D.Pisces renderer Performance and Memory enhancements
Laurent Bourgès
bourges.laurent at gmail.com
Mon Jun 17 15:18:06 UTC 2013
Jim,
I think I found the source of the 'poor' quality of line rendering:
the alpha coverage is only computed for the 2 sub pixels (x0, x1) at the
current x-coordinate of an edge ie it does not take into account the span
of a line having a very flat slope:
for (i = 0, sum = 0, prev = bboxx0; i < numCrossings; i++) {
curxo = _crossings[i];
curx = curxo >> 1;
// LBO: TODO: explain alpha computation: Jim, please ?
...
if ((sum & mask) != 0) {
x0 = (prev > bboxx0) ? prev : bboxx0; //
Math.max(prev, bboxx0);
x1 = (curx < bboxx1) ? curx : bboxx1; //
Math.min(curx, bboxx1);
if (x0 < x1) {
x0 -= bboxx0; // turn x0, x1 from coords to
indices
x1 -= bboxx0; // in the alpha array.
pix_x = x0 >> _SUBPIXEL_LG_POSITIONS_X;
pix_xmaxm1 = (x1 - 1) >>
_SUBPIXEL_LG_POSITIONS_X;
if (pix_x == pix_xmaxm1) {
// Start and end in same pixel
tmp = (x1 - x0); // number of subpixels
_alpha[pix_x] += tmp;
_alpha[pix_x + 1] -= tmp;
} else {
tmp = (x0 & _SUBPIXEL_MASK_X);
* _alpha[pix_x] += _SUBPIXEL_POSITIONS_X -
tmp;
* * _alpha[pix_x + 1] += tmp;
*
pix_xmax = x1 >> _SUBPIXEL_LG_POSITIONS_X;
tmp = (x1 & _SUBPIXEL_MASK_X);
* _alpha[pix_xmax] -= _SUBPIXEL_POSITIONS_X
- tmp;
_alpha[pix_xmax + 1] -= tmp;
* }
}
}
// to turn {0, 1} into {-1, 1}, multiply by 2 and
subtract 1.
// int crorientation = ((curxo & 0x1) << 1) - 1;
sum += ((curxo & 0x1) << 1) - 1; // crorientation;
prev = curx;
}
}
Here is a line test using GeneralPath(Line2D.float) to use pisces instead
of FillParallelogram renderer:
- pisces (8x8):
http://jmmc.fr/~bourgesl/share/java2d-pisces/linetest/LineTest_3.png
- pisces (256x256):
http://jmmc.fr/~bourgesl/share/java2d-pisces/linetest/LineTest_8.png
The artefacts comes from the fact that the line spans over several
subpixels and the slope and the span width is not used at all !
I think it is possible to compute a better coverage for all alpha pixels
implied in a span (trapezoid):
for each edge at scanline y: it only needs to have curx and previous curx
(to know how many subpixel the span crosses)
http://upload.wikimedia.org/wikipedia/commons/3/38/PolygonFillTrapezoidExample.png
Comments are welcome ...
Two more comments:
> - coordinate conversions: float or integer computations (DDA) related to
> subpixel coordinates: ceil(), floor() ...
> Pisces uses 3x3 subpixels but it provides poor quality: many
> research papers are using 4x4 (1/16 error) or 8x8 (1/64 error) subpixel
> masks to increase the coverage precision (ratio of the pixel covered by the
> polygon)
> Moreover, Pisces does not take into account the distance / error
> between the mathematical edge position and the pixel grid.
> Ideally the subpixel mask should be 16x16 => 1/256 coverage error
> but it will lead to higher processing time.
>
I misunderstood the code: pisces uses 8x8 subpixel grid (1 << 3) so every
coordinate has a 1/8 precision (low) far from 1/256 (like AGG) which is the
ultimate precision => many rasterizer uses 24.8 (24 bits for integer
coordinates, 8 bits for 1/256 precision) => DDA (32 bits integer
computations)
I will try soon to use 24.8 fixed point DDA to compute x-coordinates of
edge segments.
Laurent
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/2d-dev/attachments/20130617/7111f0b1/attachment.html>
More information about the 2d-dev
mailing list