[OpenJDK 2D-Dev] sun.java2D.Pisces renderer Performance and Memory enhancements

Jim Graham james.graham at oracle.com
Tue Jul 2 02:17:47 UTC 2013


I'd have to look, but I think we could raise our precision in the X 
direction without costing too much in performance since it just affects 
the scale of our sub-pixel contributions per pixel.  But, raising it in 
the Y direction is where the performance starts to hurt us because it 
means more differencing calculations per pixel-line.

In your examples were you raising both the X and Y sub-pixel resolutions 
to 256, or just the X resolution?  If you raised both to 256 then I 
would think that you would end up with a better result...?  I don't 
think the X resolution will help much for "nearly horizontal" lines.

I agree that it would be nice if we had a more precise calculation of 
sub-pixel coverages that did not rely on multi-sampling, and I believe 
that a decent algorithm to calculate the trapezoidal coverage of a given 
pixel would give us much better answers without any sample-count 
performance drain.

I am skeptical about using fixed point for desktop situations.  Often 
the FPU section of the processor sits idle most of the time and the 
integer unit is busy with performing calculations for the logic side of 
the process.  So, converting FP instructions to integer instructions 
just increases that bottleneck rather than sharing it.  On the other 
hand, if you are constantly converting between FP and integer then you 
have a different problem.  We sort of run into that latter problem 
because of the Java homogenous arrays which require us to store many 
integer values in our single floating point array, but I think you had a 
patch to stop doing that which would help there.

Also, 24.8 is a poor choice for fixed point.  A 256 pixel long line 
could be off by a full pixel by the end of tracing its points.  If you 
are doing 8-sub-sample AA then you would be off by a pixel after only 32 
pixels.

When I've done fixed point in the past, I've usually used longs and done 
32.32 processing.  That would require 4 billion pixels before you are 
off by a pixel.  I think the conversion to "int" is also fairly fast 
because it simply involves using the Upper Word of the result without 
much need for shifting...

			...jim

On 6/17/13 8:18 AM, Laurent Bourgès wrote:
> 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
>



More information about the 2d-dev mailing list