Skip to content

SWT drawImage Performance Regression On Windows #3419

Description

@Bio7

SWT Windows drawImage Performance Regression

Describe the bug

SWT's Canvas.drawImage() is 5–20x slower on Windows displays since around SWT 2025-12. Image zoom operations that took 5–8 ms now take 35–150 ms, causing visible UI stalling.

To Reproduce

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
import java.io.InputStream;
import java.net.URL;

public class SWTZoomPerformanceBugExample {
    private static Image image;
    private static double zoomFactor = 1.0;

    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setText("SWT Zoom Performance Test");
        shell.setSize(800, 600);
        shell.setLayout(new GridLayout(1, false));

        try {
            URL url = new URL("https://imagej.net/ij/images/NileBend.jpg");
            try (InputStream in = url.openStream()) {
                image = new Image(display, in);
            }
        } catch (Exception e) {
            image = new Image(display, 500, 500);
            GC gc = new GC(image);
            gc.fillRectangle(0, 0, 500, 500);
            gc.dispose();
        }

        Composite controls = new Composite(shell, SWT.NONE);
        controls.setLayout(new GridLayout(2, false));
        controls.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

        Label label = new Label(controls, SWT.NONE);
        label.setText("Zoom: 100%");

        Scale scale = new Scale(controls, SWT.HORIZONTAL);
        scale.setMinimum(10);
        scale.setMaximum(500);
        scale.setSelection(100);
        scale.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

        Canvas canvas = new Canvas(shell, SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND);
        canvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

        scale.addListener(SWT.Selection, e -> {
            int selection = scale.getSelection();
            zoomFactor = selection / 100.0;
            label.setText("Zoom: " + selection + "%");
            canvas.redraw();
        });

        canvas.addPaintListener(new PaintListener() {
            @Override
            public void paintControl(PaintEvent e) {
                GC gc = e.gc;
                Rectangle clientArea = canvas.getClientArea();
                gc.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
                gc.fillRectangle(clientArea);

                if (image != null && !image.isDisposed()) {
                    Rectangle srcBounds = image.getBounds();
                    int destWidth = (int) (srcBounds.width * zoomFactor);
                    int destHeight = (int) (srcBounds.height * zoomFactor);

                    gc.setAntialias(SWT.ON);
                    gc.setInterpolation(SWT.HIGH);

                    long drawStart = System.currentTimeMillis();
                    gc.drawImage(image, 0, 0, srcBounds.width, srcBounds.height, 
                                 0, 0, destWidth, destHeight);
                    long drawEnd = System.currentTimeMillis();
                    
                    System.out.println("drawImage duration: " + (drawEnd - drawStart) + " ms");
                }
            }
        });

        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }

        if (image != null && !image.isDisposed()) image.dispose();
        display.dispose();
    }
}

Steps:

  1. Run on Windows
  2. Adjust zoom slider
  3. Observe console output: drawImage duration should be ~5–8 ms but is 35–150 ms

Expected behavior

  • GC.drawImage() completes in ≤10 ms (matching SWT 2025-09)
  • Faster zoom slider interaction

Actual behavior

  • GC.drawImage() takes 35–150 ms
  • Visible UI stalling during zoom operations

Environment:

  1. Platform:

    • Windows
    • Linux
    • macOS
  2. Additional OS info:

    • Windows 10 Build 22H2 / Windows 11 Build 22H2
  3. JRE/JDK version:

    • Adoptium JDK 25

Version since

SWT 2025-12 (initial regression)

  • SWT 2025-06: ✅ ~5–8 ms (tested, working)
  • SWT 2025-09: ✅ ~5–8 ms (working according to KI analyses)
  • SWT 2025-12+: ❌ ~35–150 ms (broken)
  • SWT 2026-06: ⚠️ Slightly improved but still slow

Workarounds

  1. Revert to SWT 2025-09 (full fix)

Metadata

Metadata

Assignees

No one assigned

    Labels

    WindowsHappens on Windows OS

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions