109 lines
3.3 KiB
Java
109 lines
3.3 KiB
Java
package com.mojang.blaze3d;
|
|
|
|
import com.mojang.blaze3d.buffers.BufferType;
|
|
import com.mojang.blaze3d.buffers.BufferUsage;
|
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
|
import com.mojang.blaze3d.buffers.GpuFence;
|
|
import com.mojang.blaze3d.pipeline.RenderTarget;
|
|
import com.mojang.blaze3d.pipeline.TextureTarget;
|
|
import com.mojang.blaze3d.platform.GlStateManager;
|
|
import com.mojang.jtracy.TracyClient;
|
|
import net.fabricmc.api.EnvType;
|
|
import net.fabricmc.api.Environment;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public class TracyFrameCapture implements AutoCloseable {
|
|
private static final int MAX_WIDTH = 320;
|
|
private static final int MAX_HEIGHT = 180;
|
|
private static final int BYTES_PER_PIXEL = 4;
|
|
private int targetWidth;
|
|
private int targetHeight;
|
|
private int width;
|
|
private int height;
|
|
private final RenderTarget frameBuffer = new TextureTarget(320, 180, false);
|
|
private final GpuBuffer pixelbuffer = new GpuBuffer(BufferType.PIXEL_PACK, BufferUsage.STREAM_READ, 0);
|
|
@Nullable
|
|
private GpuFence fence;
|
|
private int lastCaptureDelay;
|
|
private boolean capturedThisFrame;
|
|
|
|
private void resize(int width, int height) {
|
|
float f = (float)width / height;
|
|
if (width > 320) {
|
|
width = 320;
|
|
height = (int)(320.0F / f);
|
|
}
|
|
|
|
if (height > 180) {
|
|
width = (int)(180.0F * f);
|
|
height = 180;
|
|
}
|
|
|
|
width = width / 4 * 4;
|
|
height = height / 4 * 4;
|
|
if (this.width != width || this.height != height) {
|
|
this.width = width;
|
|
this.height = height;
|
|
this.frameBuffer.resize(width, height);
|
|
this.pixelbuffer.resize(width * height * 4);
|
|
if (this.fence != null) {
|
|
this.fence.close();
|
|
this.fence = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void capture(RenderTarget renderTarget) {
|
|
if (this.fence == null && !this.capturedThisFrame) {
|
|
this.capturedThisFrame = true;
|
|
if (renderTarget.width != this.targetWidth || renderTarget.height != this.targetHeight) {
|
|
this.targetWidth = renderTarget.width;
|
|
this.targetHeight = renderTarget.height;
|
|
this.resize(this.targetWidth, this.targetHeight);
|
|
}
|
|
|
|
GlStateManager._glBindFramebuffer(36009, this.frameBuffer.frameBufferId);
|
|
GlStateManager._glBindFramebuffer(36008, renderTarget.frameBufferId);
|
|
GlStateManager._glBlitFrameBuffer(0, 0, renderTarget.width, renderTarget.height, 0, 0, this.width, this.height, 16384, 9729);
|
|
GlStateManager._glBindFramebuffer(36008, 0);
|
|
GlStateManager._glBindFramebuffer(36009, 0);
|
|
this.pixelbuffer.bind();
|
|
GlStateManager._glBindFramebuffer(36008, this.frameBuffer.frameBufferId);
|
|
GlStateManager._readPixels(0, 0, this.width, this.height, 6408, 5121, 0L);
|
|
GlStateManager._glBindFramebuffer(36008, 0);
|
|
this.fence = new GpuFence();
|
|
this.lastCaptureDelay = 0;
|
|
}
|
|
}
|
|
|
|
public void upload() {
|
|
if (this.fence != null) {
|
|
if (this.fence.awaitCompletion(0L)) {
|
|
this.fence = null;
|
|
|
|
try (GpuBuffer.ReadView readView = this.pixelbuffer.read()) {
|
|
if (readView != null) {
|
|
TracyClient.frameImage(readView.data(), this.width, this.height, this.lastCaptureDelay, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void endFrame() {
|
|
this.lastCaptureDelay++;
|
|
this.capturedThisFrame = false;
|
|
TracyClient.markFrame();
|
|
}
|
|
|
|
public void close() {
|
|
if (this.fence != null) {
|
|
this.fence.close();
|
|
this.fence = null;
|
|
}
|
|
|
|
this.pixelbuffer.close();
|
|
this.frameBuffer.destroyBuffers();
|
|
}
|
|
}
|