Skip to content

Commit bbfaf62

Browse files
authored
Reuse the BufferedImage in SwingOffscreenRenderer (#996)
Fix for https://youtrack.jetbrains.com/issue/CMP-6722/Excessive-garbage-generation-from-redrawing Previously, the `draw` method would allocate a `BufferedImage` on every redraw, which is wasteful. This fix changed `SwingOffscreenRenderer` to reuse the same instance of `BufferedImage` and only clear it on redraws. Only changing the draw size would allocate a new `BufferedImage`.
1 parent b73b374 commit bbfaf62

File tree

1 file changed

+11
-1
lines changed

1 file changed

+11
-1
lines changed

skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/SwingOffscreenDrawer.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ internal class SwingOffscreenDrawer(
1515
) {
1616
@Volatile
1717
private var volatileImage: VolatileImage? = null
18+
private var bufferedImage: BufferedImage? = null
19+
private var bufferedImageGraphics: Graphics2D? = null
1820

1921
/**
2022
* Draws rendered image that is represented by [bytes] on [g].
@@ -56,7 +58,15 @@ internal class SwingOffscreenDrawer(
5658
dirtyRectangles: List<Rectangle>
5759
): BufferedImage {
5860
val src = ByteBuffer.wrap(bytes)
59-
val image = BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE)
61+
if (bufferedImage == null || bufferedImage?.width != width || bufferedImage?.height != height) {
62+
bufferedImage?.flush()
63+
bufferedImage = BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE)
64+
bufferedImageGraphics = bufferedImage?.createGraphics()
65+
} else {
66+
bufferedImageGraphics?.clearRect(0,0, width, height)
67+
}
68+
val image = bufferedImage!!
69+
6070
val dstData = (image.raster.dataBuffer as DataBufferInt).data
6171
val srcData: IntBuffer = src.order(ByteOrder.LITTLE_ENDIAN).asIntBuffer()
6272
for (rect in dirtyRectangles) {

0 commit comments

Comments
 (0)