Java AWT drawImage condition - how to use synchronized to avoid it

After many hours of debugging and analysis, I finally managed to isolate the cause of the race condition. The solution to another question!

To see the status of the race in action, I recorded a video during debugging. Since then I have improved my understanding of the situation, so please forgive the bad comments and silly mechanisms implemented as part of the debugging process.

http://screencast.com/t/aTAk1NOVanjR

So the situation: we have a double buffered implementation of the surface (for example, java.awt.Frame or Window), where there is a continuous stream that essentially cycles through, invoking the rendering process (which performs the layout of the user interface and displays it to the backbuffer), and then, post-render, blits the rendered area from the backbuffer to the screen.

Here's the pseudo-code version (full version of line 824 of Surface.java ) of a double buffered render:

public RenderedRegions render() {
    // pseudo code
    RenderedRegions r = super.render();
    if (r==null) // nothing rendered
        return
    for (region in r)
        establish max bounds
    blit(max bounds)
    return r;
}

As with any AWT surface implementation, it also implements (line 507 in AWT.java - link limit :( - use the Surface.java link, replace core / Surface.java with plat / AWT.java) paint override / update which also close from buffer to screen:

        public void paint(Graphics gr) {
            Rectangle r = gr.getClipBounds();
            refreshFromBackbuffer(r.x - leftInset, r.y - topInset, r.width, r.height);
        }

Blitting is executed (line 371 in AWT.java) using the drawImage () function:

    /** synchronized as otherwise it is possible to blit before images have been rendered to the backbuffer */
    public synchronized void blit(PixelBuffer s, int sx, int sy, int dx, int dy, int dx2, int dy2) {
        discoverInsets();
        try {
            window.getGraphics().drawImage(((AWTPixelBuffer)s).i,
                              dx + leftInset, dy + topInset,     // destination topleft corner
                              dx2 + leftInset, dy2 + topInset,   // destination bottomright corner
                              sx, sy,                            // source topleft corner
                              sx + (dx2 - dx), sy + (dy2 - dy),  // source bottomright corner
                              null);
        } catch (NullPointerException npe) { /* FIXME: handle this gracefully */ }
    }

(: !)

, drawImage blit refreshBackBuffer() paint/update , .

... blit . .: (

, :

  • re-blit
    : , - - ( → → )

  • blit paint/update,

    : , ,

(1) . : (2) , ... (1) , , .

, , - , , - drawImage().

, , ImageObserver?

, - (Vexi, , , , 2 ), paint/update - script ( ) script.

+3
2

: : AWT -


, blitting paint(), - backbuffer . , , , , , , .

(). Java , , BufferStrategy, Direct3d +.

paint() update() . , - .

private class InnerFrame extends Frame() {
    public void update(Graphics g) { }
    public void paint(Graphics g) { }
    ....
}

, 100% , , , BufferStrategy, show() .

Swing, - . JLabel ImageIcon, ( EDT) , ImageIcon.

, , , , , , , - , .

0

, , Blit AWT?

0

Source: https://habr.com/ru/post/1791103/


All Articles