Skip to content

Commit

Permalink
Reuse the BufferedImage in SwingOffscreenRenderer (#996)
Browse files Browse the repository at this point in the history
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`.
  • Loading branch information
samofcorinth authored Oct 22, 2024
1 parent b73b374 commit bbfaf62
Showing 1 changed file with 11 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ internal class SwingOffscreenDrawer(
) {
@Volatile
private var volatileImage: VolatileImage? = null
private var bufferedImage: BufferedImage? = null
private var bufferedImageGraphics: Graphics2D? = null

/**
* Draws rendered image that is represented by [bytes] on [g].
Expand Down Expand Up @@ -56,7 +58,15 @@ internal class SwingOffscreenDrawer(
dirtyRectangles: List<Rectangle>
): BufferedImage {
val src = ByteBuffer.wrap(bytes)
val image = BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE)
if (bufferedImage == null || bufferedImage?.width != width || bufferedImage?.height != height) {
bufferedImage?.flush()
bufferedImage = BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE)
bufferedImageGraphics = bufferedImage?.createGraphics()
} else {
bufferedImageGraphics?.clearRect(0,0, width, height)
}
val image = bufferedImage!!

val dstData = (image.raster.dataBuffer as DataBufferInt).data
val srcData: IntBuffer = src.order(ByteOrder.LITTLE_ENDIAN).asIntBuffer()
for (rect in dirtyRectangles) {
Expand Down

0 comments on commit bbfaf62

Please sign in to comment.