minecraft-src/com/mojang/blaze3d/opengl/GlDebug.java
2025-07-04 03:45:38 +03:00

198 lines
5.6 KiB
Java

package com.mojang.blaze3d.opengl;
import com.google.common.collect.EvictingQueue;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.mojang.blaze3d.platform.DebugMemoryUntracker;
import com.mojang.blaze3d.platform.GLX;
import com.mojang.logging.LogUtils;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.opengl.ARBDebugOutput;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GLCapabilities;
import org.lwjgl.opengl.GLDebugMessageARBCallback;
import org.lwjgl.opengl.GLDebugMessageCallback;
import org.lwjgl.opengl.KHRDebug;
import org.slf4j.Logger;
@Environment(EnvType.CLIENT)
public class GlDebug {
private static final Logger LOGGER = LogUtils.getLogger();
private static final int CIRCULAR_LOG_SIZE = 10;
private final Queue<GlDebug.LogEntry> MESSAGE_BUFFER = EvictingQueue.create(10);
@Nullable
private volatile GlDebug.LogEntry lastEntry;
private static final List<Integer> DEBUG_LEVELS = ImmutableList.of(37190, 37191, 37192, 33387);
private static final List<Integer> DEBUG_LEVELS_ARB = ImmutableList.of(37190, 37191, 37192);
private static String printUnknownToken(int token) {
return "Unknown (0x" + Integer.toHexString(token).toUpperCase() + ")";
}
public static String sourceToString(int source) {
switch (source) {
case 33350:
return "API";
case 33351:
return "WINDOW SYSTEM";
case 33352:
return "SHADER COMPILER";
case 33353:
return "THIRD PARTY";
case 33354:
return "APPLICATION";
case 33355:
return "OTHER";
default:
return printUnknownToken(source);
}
}
public static String typeToString(int type) {
switch (type) {
case 33356:
return "ERROR";
case 33357:
return "DEPRECATED BEHAVIOR";
case 33358:
return "UNDEFINED BEHAVIOR";
case 33359:
return "PORTABILITY";
case 33360:
return "PERFORMANCE";
case 33361:
return "OTHER";
case 33384:
return "MARKER";
default:
return printUnknownToken(type);
}
}
public static String severityToString(int type) {
switch (type) {
case 33387:
return "NOTIFICATION";
case 37190:
return "HIGH";
case 37191:
return "MEDIUM";
case 37192:
return "LOW";
default:
return printUnknownToken(type);
}
}
private void printDebugLog(int source, int type, int id, int severity, int length, long message, long userProgram) {
String string = GLDebugMessageCallback.getMessage(length, message);
GlDebug.LogEntry logEntry;
synchronized (this.MESSAGE_BUFFER) {
logEntry = this.lastEntry;
if (logEntry != null && logEntry.isSame(source, type, id, severity, string)) {
logEntry.count++;
} else {
logEntry = new GlDebug.LogEntry(source, type, id, severity, string);
this.MESSAGE_BUFFER.add(logEntry);
this.lastEntry = logEntry;
}
}
LOGGER.info("OpenGL debug message: {}", logEntry);
}
public List<String> getLastOpenGlDebugMessages() {
synchronized (this.MESSAGE_BUFFER) {
List<String> list = Lists.<String>newArrayListWithCapacity(this.MESSAGE_BUFFER.size());
for (GlDebug.LogEntry logEntry : this.MESSAGE_BUFFER) {
list.add(logEntry + " x " + logEntry.count);
}
return list;
}
}
@Nullable
public static GlDebug enableDebugCallback(int vebosity, boolean sychronous, Set<String> enabledExtensions) {
if (vebosity <= 0) {
return null;
} else {
GLCapabilities gLCapabilities = GL.getCapabilities();
if (gLCapabilities.GL_KHR_debug && GlDevice.USE_GL_KHR_debug) {
GlDebug glDebug = new GlDebug();
enabledExtensions.add("GL_KHR_debug");
GL11.glEnable(37600);
if (sychronous) {
GL11.glEnable(33346);
}
for (int i = 0; i < DEBUG_LEVELS.size(); i++) {
boolean bl = i < vebosity;
KHRDebug.glDebugMessageControl(4352, 4352, (Integer)DEBUG_LEVELS.get(i), (int[])null, bl);
}
KHRDebug.glDebugMessageCallback(GLX.make(GLDebugMessageCallback.create(glDebug::printDebugLog), DebugMemoryUntracker::untrack), 0L);
return glDebug;
} else if (gLCapabilities.GL_ARB_debug_output && GlDevice.USE_GL_ARB_debug_output) {
GlDebug glDebug = new GlDebug();
enabledExtensions.add("GL_ARB_debug_output");
if (sychronous) {
GL11.glEnable(33346);
}
for (int i = 0; i < DEBUG_LEVELS_ARB.size(); i++) {
boolean bl = i < vebosity;
ARBDebugOutput.glDebugMessageControlARB(4352, 4352, (Integer)DEBUG_LEVELS_ARB.get(i), (int[])null, bl);
}
ARBDebugOutput.glDebugMessageCallbackARB(GLX.make(GLDebugMessageARBCallback.create(glDebug::printDebugLog), DebugMemoryUntracker::untrack), 0L);
return glDebug;
} else {
return null;
}
}
}
@Environment(EnvType.CLIENT)
static class LogEntry {
private final int id;
private final int source;
private final int type;
private final int severity;
private final String message;
int count = 1;
LogEntry(int source, int type, int id, int severity, String message) {
this.id = id;
this.source = source;
this.type = type;
this.severity = severity;
this.message = message;
}
boolean isSame(int source, int type, int id, int severity, String message) {
return type == this.type && source == this.source && id == this.id && severity == this.severity && message.equals(this.message);
}
public String toString() {
return "id="
+ this.id
+ ", source="
+ GlDebug.sourceToString(this.source)
+ ", type="
+ GlDebug.typeToString(this.type)
+ ", severity="
+ GlDebug.severityToString(this.severity)
+ ", message='"
+ this.message
+ "'";
}
}
}