[OpenJDK 2D-Dev] HiDPI support issues on Windows
anton.tarasov at jetbrains.com
Tue Oct 4 20:01:55 UTC 2016
On 10/4/2016 1:05 AM, Jim Graham wrote:
> Hi Anton,
> Yes, the numbers you are describing are consistent with performing
> that standard boilerplate using an origin/translate that is not
> exactly at an integer pixel location.
> My comments about our mechanisms not allowing for scale-aware
> allocations can be dealt with in a couple of ways:
> - Add some internal pixel-based interfaces for scale aware code, like
> RepaintManager (and consider making them public for applications to use)
Ok, that's clear.
> - Simply ask for a large enough integer to make sure you got the
> entire clip to fit in it and let the allocator give you an even larger
> image. It doesn't matter if you paint into a larger image (other than
> having to allocate an extra row/column on occasion). After that, as
> long as you set the translates and clip to exact pixel locations
> within the temp image, you should be fine. You also have to deal with
> limiting your blit to the destination, probably using drawImage(dxy12,
> sxy12) variant
That's not quite clear, sorry. Are you talking about a scale-aware
image? How does its size helps if we still translate/clip?
Anyway, I roughly tried your approach mentioned in the previous e-mail,
but forcing RM to paint via offscreen BufferedImage, not volatile (just
for a quick check).
It solved the shift issue of the demo listed in 8162350, which is cool.
It also solved the traces of InternalFrame and menu in SwingSet2.
Scrolling still traces (I suppose it should be resolved in
Also, the problem with primitives rendering
is still there. But it seems to relate to line-thikness
(border-thickness) rounding inaccuracy. What we can do with that?...
> On 10/3/2016 2:41 PM, Anton Tarasov wrote:
>> Hi Alexandr,
>> I looked at the testcase 8162350 closely and found your explanation
>> below not quite precise...
>> When you repaint a letter with an slightly expanded dirty rect, you've
>> got it as [40-1, 0-1, 80+2, 60+2] = [39, -1, 82, 62]. Let's count
>> only "x".
>> As Jim noted, the code to draw is:
>> // repainting x,y,w,h
>> img = make image (w,h)
>> g = img.getGraphics()
>> destination.drawImage(img, x,y)
>> The transformation matrix of "g" is double (AffineTransform.java). So,
>> g.translate(-39) translates to -39*1.5=-58.5. The top-left pixel of the
>> letter [40, 0]=[40*1.5, 0]=[60, 0] thus is painted into x=[60-58.5]=1.5
>> of the intermediate "img". And I suspect it's eventually not rounded up
>> but is floor'ed to x=1. Then, the "img" is drawn at x==[39*1.5]=58.5
>> which I suspect is also eventually floor'ed to x=58. As the result, the
>> top-left pixel of the letter appears at x=[58+1]=59, not at x=60. That's
>> the shift. Not sure if my guess is correct though.
>> The Jim's last suggestion seems to address the problem, as it scales &
>> rounds first and then passes already computed values down. Does the
>> solution affect RepaintManager only? Or I suspect there will be a
>> problem with:
>> // Not sure if there is a mechanism for this since I think
>> // all of the interfaces to get a compatible image are
>> // designed to assume that the caller is not scale-aware.
>> img = make pixel-sized image (pixelw, pixelh)
>> because the comments are true.
>> On 9/30/2016 1:22 PM, Alexandr Scherbatiy wrote:
>>> Hello Anton,
>>> Yes, we are working on it.
>>> For example, there is the known issue DK-8162350 RepaintManager shifts
>>> repainted region when the floating point UI scale is used.
>>> The problem is that the RepaintManager draws a region to a buffered
>>> image at first and draws the image after that to the window.
>>> Suppose the image has int coordinates and size (x, y, w, h) in the
>>> user space. It should be drawn into the region with coordinates (x, y,
>>> x+width, y+height) = (x1, y1, x2, y2).
>>> If floating point UI scale is used (like 1.5) the region coordinates
>>> are converted to values (1.5 * x1, 1.5 * y1, 1.5 * x2, 1.5 * y2) in
>>> the dev space.
>>> Now these coordinates need to be rounded and the process really
>>> depends on the evenness or oddness of the start and end coordinates.
>>> They both can be rounded to one side or to opposite. Depending on this
>>> some lines near the drawn image region can be not filled or just
>>> wrongly filled.
>>> If I try to not use a buffered image in the RepaintManager it seems
>>> that some problems are just gone away (internal frame moving artifacts
>>> on the SwingSet2 demo or squares in MinimalSwingApplication are drawn
>>> as squares and not rectangles).
>>> But not all of them. The artifacts during the scrolling in the
>>> SwingSet2 demo still exist.
>>> I have filled an issue on it just to keep track of them: JDK-8166954
>>> Drawing artifacts with floating point UI scale
>>> The another problem which we are working on is that a selected text is
>>> just shifted: 8156217 Selected text is shifted on HiDPI display
>>> To support this we were needed to add some new API which support
>>> floating point coordinates in the View, TextUI and JTextComponent
>>> The issue is on the review:
>>> On 9/28/2016 1:17 PM, Anton Tarasov wrote:
>>>> JDK9 comes with HiDPI support on Windows/Linux which is really great.
>>>> As we gave it a try, we found it looking pretty good with an integer
>>>> scale (2x) but revealed some rendering flaws with float scales.
>>>> Let me please demonstrate it with SwingSet2 + JDK9-ea-b137 + Windows
>>>> 8.1 in 150% scale (1.5f)
>>>> demo1 <http://cr.openjdk.java.net/%7Eant/hidpi_pics/demo1.png>
>>>> Dragging Frame-0 behind the pallet makes the pallet wavy.
>>>> Also, as Frame-0 moves it may leave traces.
>>>> demo2 <http://cr.openjdk.java.net/%7Eant/hidpi_pics/demo2.png>
>>>> Unstable look of a control. For instance, these two combos are
>>>> decorated differently (and not perfectly).
>>>> demo3 <http://cr.openjdk.java.net/%7Eant/hidpi_pics/demo3.png>
>>>> Scrolling traces.
>>>> demo4 <http://cr.openjdk.java.net/%7Eant/hidpi_pics/demo4.png>
>>>> Menu traces.
>>>> Colored rendering artifacts.
>>>> Additionally, I'm attaching a test source & pics kindly provided by
>>>> Renaud (cc'd) from AndroidStudio. The demo finely shows problems on
>>>> the example of primitive rendering.
>>>> Scaling 100%
>>>> Scaling 125%
>>>> Scaling 150%
>>>> It seems like most of the mentioned issues are caused by inaccurate
>>>> rounding performed during the rendering cycle.
>>>> So, I'd like to ask you please share your thoughts on it. How serious
>>>> is the problem at all (I guess you're aware of it)? What is solvable
>>>> on the JDK side, and what is not (e.g. demo2 and the Renaud's test
>>>> Do you have plans to resolve it by jdk9 GA, or earlier/later? Any
>>>> technical details behind it are very welcome as well.
>>>> Thanks in advance,
More information about the 2d-dev