|
| 1 | +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Barnaby <22575741+barnabwhy@users.noreply.github.com> |
| 3 | +Date: Sat, 29 Jun 2024 12:06:51 +0100 |
| 4 | +Subject: [PATCH] Reduce work done in CraftMapCanvas.drawImage by limiting size |
| 5 | + of image and using System.arraycopy instead of for loops and use bitwise |
| 6 | + operations to do bounds checks. |
| 7 | + |
| 8 | + |
| 9 | +diff --git a/src/main/java/org/bukkit/craftbukkit/map/CraftMapCanvas.java b/src/main/java/org/bukkit/craftbukkit/map/CraftMapCanvas.java |
| 10 | +index ff59f759669620795ef355c988b664bdcda39f52..a5e98571d6d83390761c11e28a0bc3c4415799cd 100644 |
| 11 | +--- a/src/main/java/org/bukkit/craftbukkit/map/CraftMapCanvas.java |
| 12 | ++++ b/src/main/java/org/bukkit/craftbukkit/map/CraftMapCanvas.java |
| 13 | +@@ -91,12 +91,41 @@ public class CraftMapCanvas implements MapCanvas { |
| 14 | + |
| 15 | + @Override |
| 16 | + public void drawImage(int x, int y, Image image) { |
| 17 | +- byte[] bytes = MapPalette.imageToBytes(image); |
| 18 | +- for (int x2 = 0; x2 < image.getWidth(null); ++x2) { |
| 19 | +- for (int y2 = 0; y2 < image.getHeight(null); ++y2) { |
| 20 | +- this.setPixel(x + x2, y + y2, bytes[y2 * image.getWidth(null) + x2]); |
| 21 | ++ // Paper start - Reduce work done by limiting size of image and using System.arraycopy |
| 22 | ++ int width = 128 - x; |
| 23 | ++ int height = 128 - y; |
| 24 | ++ if (image.getHeight(null) < height) |
| 25 | ++ height = image.getHeight(null); |
| 26 | ++ |
| 27 | ++ // Create a subimage if the image is larger than the max allowed size |
| 28 | ++ java.awt.image.BufferedImage temp; |
| 29 | ++ if (image.getWidth(null) >= width && image instanceof java.awt.image.BufferedImage bImage) { |
| 30 | ++ // If the image is larger than the max allowed size, get a subimage, otherwise use the image as is |
| 31 | ++ if (image.getWidth(null) > width || image.getHeight(null) > height) { |
| 32 | ++ temp = bImage.getSubimage(0, 0, width, height); |
| 33 | ++ } else { |
| 34 | ++ temp = bImage; |
| 35 | + } |
| 36 | ++ } else { |
| 37 | ++ temp = new java.awt.image.BufferedImage(width, height, java.awt.image.BufferedImage.TYPE_INT_ARGB); |
| 38 | ++ java.awt.Graphics2D graphics = temp.createGraphics(); |
| 39 | ++ graphics.drawImage(image, 0, 0, null); |
| 40 | ++ graphics.dispose(); |
| 41 | + } |
| 42 | ++ |
| 43 | ++ byte[] bytes = MapPalette.imageToBytes(temp); |
| 44 | ++ |
| 45 | ++ // Since we now control the size of the image, we can safely use System.arraycopy |
| 46 | ++ // If x is 0, we can just copy the entire image as width is 128 and height is <=(128-y) |
| 47 | ++ if (x == 0) { |
| 48 | ++ System.arraycopy(bytes, 0, this.buffer, y * 128, width * height); |
| 49 | ++ return; |
| 50 | ++ } |
| 51 | ++ |
| 52 | ++ for (int y2 = 0; y2 < height; ++y2) { |
| 53 | ++ System.arraycopy(bytes, 0, this.buffer, (y + y2) * 128 + x, width); |
| 54 | ++ } |
| 55 | ++ // Paper end |
| 56 | + } |
| 57 | + |
| 58 | + @Override |
| 59 | +diff --git a/src/main/java/org/bukkit/craftbukkit/map/CraftMapRenderer.java b/src/main/java/org/bukkit/craftbukkit/map/CraftMapRenderer.java |
| 60 | +index 0cbbd915631904fe8c6effefb92895422b33eff6..cf0920e5f84b35647882fb963e9972af4e8427e0 100644 |
| 61 | +--- a/src/main/java/org/bukkit/craftbukkit/map/CraftMapRenderer.java |
| 62 | ++++ b/src/main/java/org/bukkit/craftbukkit/map/CraftMapRenderer.java |
| 63 | +@@ -23,8 +23,10 @@ public class CraftMapRenderer extends MapRenderer { |
| 64 | + @Override |
| 65 | + public void render(MapView map, MapCanvas canvas, Player player) { |
| 66 | + // Map |
| 67 | +- for (int x = 0; x < 128; ++x) { |
| 68 | +- for (int y = 0; y < 128; ++y) { |
| 69 | ++ // Paper start - Swap inner and outer loops here to (theoretically) improve cache locality |
| 70 | ++ for (int y = 0; y < 128; ++y) { |
| 71 | ++ for (int x = 0; x < 128; ++x) { |
| 72 | ++ // Paper end |
| 73 | + canvas.setPixel(x, y, this.worldMap.colors[y * 128 + x]); |
| 74 | + } |
| 75 | + } |
0 commit comments