try to fix graphics path

This commit is contained in:
2026-06-01 02:18:01 +02:00
parent ebf87c0bff
commit 5f0edcbe31
3 changed files with 34 additions and 26 deletions

4
.ignore Normal file
View File

@@ -0,0 +1,4 @@
.gradle
bin
result
.worktrees

8
flake.lock generated
View File

@@ -70,11 +70,11 @@
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs"
}, },
"locked": { "locked": {
"lastModified": 1780258814, "lastModified": 1780272954,
"narHash": "sha256-8rxL7xaZ/loYg3zdt0w5+hfNyHFVknDZN360NzrtCsQ=", "narHash": "sha256-bVWY60iw8yPIu7I8FuRPf06T0H1TDvQDVUlzeHQs8UA=",
"ref": "refs/heads/main", "ref": "refs/heads/main",
"rev": "6a3d5aa0b0b1f738c958e2a2f0249574c07d9c4d", "rev": "06a9d5d3ecf11c58f0e41214d1b59900e672dd3a",
"revCount": 23, "revCount": 24,
"type": "git", "type": "git",
"url": "https://gitea.gregorlohaus.com/gregor/jlibghostty.git" "url": "https://gitea.gregorlohaus.com/gregor/jlibghostty.git"
}, },

View File

@@ -1,8 +1,8 @@
package com.gregor.jprototerm; package com.gregor.jprototerm;
import dev.jlibghostty.KittyImage;
import dev.jlibghostty.KittyImageCompression; import dev.jlibghostty.KittyImageCompression;
import dev.jlibghostty.KittyImageFormat; import dev.jlibghostty.KittyImageFormat;
import dev.jlibghostty.KittyImageSnapshot;
import dev.jlibghostty.KittyPlacement; import dev.jlibghostty.KittyPlacement;
import dev.jlibghostty.KittyPlacementLayer; import dev.jlibghostty.KittyPlacementLayer;
import dev.jlibghostty.KittyPlaceholder; import dev.jlibghostty.KittyPlaceholder;
@@ -461,7 +461,7 @@ final class GhosttyTerminalRenderer extends TerminalRenderer {
private static boolean hasKittyGraphics(RenderTarget target) { private static boolean hasKittyGraphics(RenderTarget target) {
return target.kittyGraphics() return target.kittyGraphics()
.map(graphics -> !graphics.placements().isEmpty()) .map(graphics -> !graphics.isEmpty())
.orElse(false); .orElse(false);
} }
@@ -601,16 +601,17 @@ final class GhosttyTerminalRenderer extends TerminalRenderer {
} }
private Image imageFor(KittyPlacement placement) { private Image imageFor(KittyPlacement placement) {
return placement.image().map(snapshot -> { return placement.image().map(image -> {
byte[] data = snapshot.data(); // Build the cache key from cheap metadata only — the pixel buffer is never copied out
KittyImageKey key = KittyImageKey.of(snapshot, data); // of native memory on a cache hit (the common per-frame case).
KittyImageKey key = KittyImageKey.of(image);
Image cached = kittyImageCache.get(key); Image cached = kittyImageCache.get(key);
if (cached != null) { if (cached != null) {
return cached; return cached;
} }
kittyImageCache.keySet().removeIf(existing -> existing.id() == snapshot.id()); kittyImageCache.keySet().removeIf(existing -> existing.id() == image.id());
Image decoded = decodeImage(snapshot, data); Image decoded = decodeImage(image);
if (decoded != null) { if (decoded != null) {
kittyImageCache.put(key, decoded); kittyImageCache.put(key, decoded);
} }
@@ -618,22 +619,25 @@ final class GhosttyTerminalRenderer extends TerminalRenderer {
}).orElse(null); }).orElse(null);
} }
private Image decodeImage(KittyImageSnapshot snapshot, byte[] data) { private Image decodeImage(KittyImage source) {
if (snapshot.compression() != KittyImageCompression.NONE) { if (source.compression() != KittyImageCompression.NONE) {
return null; return null;
} }
if (snapshot.format() == KittyImageFormat.PNG) { // Only now — on a cache miss — do we pull the raw bytes across the native boundary.
byte[] data = source.data();
KittyImageFormat format = source.format();
if (format == KittyImageFormat.PNG) {
return new Image(new ByteArrayInputStream(data)); return new Image(new ByteArrayInputStream(data));
} }
int width = Math.toIntExact(snapshot.width()); int width = Math.toIntExact(source.width());
int height = Math.toIntExact(snapshot.height()); int height = Math.toIntExact(source.height());
WritableImage image = new WritableImage(width, height); WritableImage image = new WritableImage(width, height);
if (snapshot.format() == KittyImageFormat.RGBA) { if (format == KittyImageFormat.RGBA) {
image.getPixelWriter().setPixels(0, 0, width, height, PixelFormat.getByteBgraInstance(), rgbaToBgra(data), 0, width * 4); image.getPixelWriter().setPixels(0, 0, width, height, PixelFormat.getByteBgraInstance(), rgbaToBgra(data), 0, width * 4);
} else if (snapshot.format() == KittyImageFormat.RGB) { } else if (format == KittyImageFormat.RGB) {
image.getPixelWriter().setPixels(0, 0, width, height, PixelFormat.getByteRgbInstance(), data, 0, width * 3); image.getPixelWriter().setPixels(0, 0, width, height, PixelFormat.getByteRgbInstance(), data, 0, width * 3);
} }
return image; return image;
@@ -1321,15 +1325,15 @@ final class GhosttyTerminalRenderer extends TerminalRenderer {
// identity + dimensions + payload length are enough to key the decoded-image cache, and // identity + dimensions + payload length are enough to key the decoded-image cache, and
// we avoid fingerprinting the whole payload — which previously ran once per frame per // we avoid fingerprinting the whole payload — which previously ran once per frame per
// placement (O(image size)) just to look the image up. // placement (O(image size)) just to look the image up.
private record KittyImageKey(long id, long number, long width, long height, KittyImageFormat format, int dataLength) { private record KittyImageKey(long id, long number, long width, long height, KittyImageFormat format, long dataLength) {
private static KittyImageKey of(KittyImageSnapshot snapshot, byte[] data) { private static KittyImageKey of(KittyImage image) {
return new KittyImageKey( return new KittyImageKey(
snapshot.id(), image.id(),
snapshot.number(), image.number(),
snapshot.width(), image.width(),
snapshot.height(), image.height(),
snapshot.format(), image.format(),
data.length image.dataLength()
); );
} }
} }