Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8209329

[macos] non-opaque Swing window flickers

    XMLWordPrintable

Details

    • Bug
    • Resolution: Duplicate
    • P4
    • tbd
    • 8u161, 10.0.1, 11, 12
    • client-libs

    Description

      When a non-opaque Swing window is resized, it occasionally displays the bare window background for brief periods of time, which is perceived as a flicker. This behavior is timing dependent. The attached test programs demonstrate the problem on my macOS system, although the results vary with different JDK releases. The programs may or may not demonstrate the problem on other systems. Although the problem was discovered on macOS, the logical flaw that it reveals is platform independent, so the problem may exist on other platforms as well. The flaw is not dependent on window resizing. On my system, it also occurs when the window is first displayed. It might occur in other situations as well.

      The cause of this behavior is a flaw in the implementation of Swing repaint. Swing repaint is designed to ensure that incomplete renderings are never visible. The implementation uses an offscreen buffer rather than synchronization to achieve this goal. Repainting is performed by drawing to an offscreen buffer. When repainting is complete, the offscreen buffer is copied to the window frame buffer as an atomic operation.

      The flaw is that, when the window is not opaque, the window background color may be painted directly to the frame buffer at the beginning of the repaint operation. The code that paints the background is the Window.paint() method. The effect is that during a short interval of time until the offscreen buffer is drawn, the window frame buffer will contain only the bare window background. Should the frame buffer be accessed during that time to update the native window, the bare window background will become visible. It will remain visible until the repaint completes.

      On macOS, there are two circumstances where an AppKit generated upcall causes the window frame buffer to be copied to the native window (the AWTView layer). The first is when AppKit believes the AWTView needs to be updated. This happens when the window is first created and thereafter when triggered by Java telling AppKit that the AWTView needs to be updated. AWT responds to this upcall by copying the contents of the frame buffer to the AWTView layer. The second is when AppKit notifies AWT that the window has been resized. In response, AWT creates a new frame buffer and copies the contents of the old frame buffer to the new frame buffer. In both cases, the upcalls are performed on the AppKit main thread and are not synchronized with Swing repainting. If the frame buffer is accessed while it contains only the bare window background, that is what will be copied to the AWTView layer and made visible.

      Without resizing, this problem is less likely to occur. When the Swing repaint is finished, AppKit is notified that the AWTView needs to be redrawn. Generally, the redraw occurs before the next repaint, so no flicker is observed.

      I have verified this explanation:

      1. If I change Window.paint() to paint a red background, the flicker is red.
      2. If I change Window.paint() to not paint a background, there is no flicker.
      3. By instrumenting the JDK, I have observed that both of the above upcall scenarios have occurred during the time when the frame buffer contains only the background color. The observations were made during a test run in which flickering was observed.

      Attachments

        Issue Links

          Activity

            People

              Unassigned Unassigned
              alans Alan Snyder
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: