<AWT Dev> [9] Review Request: JDK-8029455 JLightweightFrame: support scaled painting
Jim Graham
james.graham at oracle.com
Wed Dec 11 13:44:40 PST 2013
Hi Anton,
On 12/11/13 5:13 AM, Anton V. Tarasov wrote:
> Hi Jim,
>
> On 11.12.2013 13:14, Jim Graham wrote:
>>
>> In BufferedImage, the private fields and methods will require an
>> accessor method for the inner class to access them. Is there a reason
>> they can't be left package-accessible?
>
> Sorry, I don't clearly understand what you mean... The "scale" private
> field and the new methods are accessed from other packages, so I can't
> make them package-private. I've added the accessor which I put into
> OffscreenImage (an internal class).
This is entirely an internal detail related to how inner classes are
implemented (like the class that you use to allow OffscreenImage to
access the BI methods).
The inner "accessor helper" class is technically outside the class scope
of the BufferedImage class - it is a separate class and it is restricted
in the byte code interpreter to the same access privileges as any other
"separate class", but the methods it calls on BI are private. The
runtime does not allow this, but the compiler wants you to think this is
possible for convenience of writing inner classes. As a result, it
injects fake accessor calls into the BI class that allow the inner
classes to call private methods on BI. Dump the byte codes of the
relevant classes with javap and you will see the shadow calls that break
the privacy of those methods. Those methods are not allowed from java
code, only the inner class magic can use them. It is byte-code magic to
enable the syntactic sugar of inner classes.
I believe if you just make the new methods on BI package-private instead
of fully class-private, then those helper inner-class-only accessor
methods aren't needed.
>> In JViewport, is there a reason why a map of various scaled backing
>> stores are kept rather than just validating the existing backing store
>> against the new desired scale and replacing it when it changes? Does
>> the scale on the backing store ping-pong back and forth between scales
>> much?
>
> This doesn't ping-pong much, indeed. So you want to say using a cache
> here is not justified? Ok, why I did that is probably to mimic the logic
> used by RepaintManager which does use a map b/w graphic configs and
> volatile images (the volatileMap field), whereas changes of the
> GraphicsConfig shouldn't occur often.
>
> Anyway, this indeed doesn't increase performance but increases a
> footprint, so I'm ok not to use cache here.
I just wanted an analysis of whether the new complexity had any value.
It sounds like it mirrors what was done in other places and that is
fine, but perhaps this particular variant of that similar mechanism is
premature? In general, I'd wait to add complexity until a problem is
demonstrated that makes it worthwhile.
>> BufImgSurfaceData - you have to validate the transform as not flipping
>> or rotating (even quadrant rotation will violate your conditions. I
>> believe that testing the transform type with a mask consisting of the
>> TRANSLATE and SCALE_MASK flags should be fine. Also, do we wan to set
>> a precedent of allowing copyArea under an arbitrary scale, or should
>> we test it to make sure it is specifically the same scale as the
>> device scale factor?
>
> Ok, I'll check the transform for TRANSLATE/SCALE only. The same scale as
> the device works for me, so I'll limit it to that case.
Though, I do think we should eventually have copyarea work with scales.
BTW, this same code appears in SG2D, but it is rejected by a test on the
transform type. Have you thought about simply inserting your transform
code into the test for the transform type in SG2D rather than shadowing
the entire method?
>> SG2D - I'm worried about the performance impliciations of adding a new
>> method in that creates and returns an array on every drawImage call.
>> Did you do a performance test with J2DBench to verify the impact of
>> these operations?
>
> Well, this was done just to make the code more clear. I can remove that
> method (and do the instanceof check in every place I called it), or as
> an alternative I can cache the array so that not to create it (out of
> the stack) every time. Does this make sense to you? (I didn't run
> J2DBench yet).
A single SG2D should be single threaded (calling from multiple threads
is not supported and results are not guaranteed) so caching the array in
the instance would be fine. Also, we are discussing the issue of
getWidth(null) not matching the logical size of the image in another
thread. Depending on what we decide there, it may make sense to move
the scaling logic inside the getWidth() methods of the scaled buffered
images and then we need far fewer mods to SG2D. But, I think that would
only work reasonably if such "scaled buffered images" are never leaked
to the developer until we come up with a reasonable external API that
makes sense for them.
I'm going to save the rest of the reply for another message since it
gets involved...
...jim
More information about the awt-dev
mailing list