Skip to content

Commit

Permalink
This will get reworded anyway
Browse files Browse the repository at this point in the history
  • Loading branch information
Matrix89 committed Jan 17, 2021
1 parent 3ad16bd commit 2727f8a
Show file tree
Hide file tree
Showing 22 changed files with 919 additions and 633 deletions.
Binary file added 800x600.bin
Binary file not shown.
273 changes: 273 additions & 0 deletions GPUViewer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
import li.cil.sedna.device.virtio.VirtIOMouseDevice;
import li.cil.sedna.device.virtio.gpu.VirtIOGPURect;
import javafx.util.Pair;
import li.cil.sedna.api.memory.MemoryMap;
import li.cil.sedna.device.virtio.VirtIOKeyboardDevice;
import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GLUtil;
import org.lwjgl.system.MemoryStack;

import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;
import java.util.concurrent.ConcurrentLinkedQueue;

import static org.lwjgl.glfw.Callbacks.glfwFreeCallbacks;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.glBindVertexArray;
import static org.lwjgl.opengl.GL30.glGenVertexArrays;
import static org.lwjgl.system.MemoryStack.stackPush;
import static org.lwjgl.system.MemoryUtil.NULL;

public class GPUViewer {
private long window;
private final MemoryMap memoryMap;
private final VirtIOKeyboardDevice keyboard;
private final VirtIOMouseDevice mouse;

private int texture;
private int vao;
private int vertexBuffer;
private int uvBuffer;
private int shaderId;
private ConcurrentLinkedQueue<Pair<VirtIOGPURect, ByteBuffer>> updateBuffer = new ConcurrentLinkedQueue<>();
//private TestWindow testWindow = new TestWindow();

public GPUViewer(MemoryMap memoryMap,VirtIOMouseDevice mouse, VirtIOKeyboardDevice keyboard) {
this.memoryMap = memoryMap;
this.keyboard = keyboard;
this.mouse = mouse;
new Thread(() -> {
init();
initBuffers();
try {
initShaders();
} catch (Exception e) {
e.printStackTrace();
}
loop();

glfwFreeCallbacks(window);
glfwDestroyWindow(window);

glfwTerminate();
Objects.requireNonNull(glfwSetErrorCallback(null)).free();
}).start();
}

private void init() {
// Setup an error callback. The default implementation
// will print the error message in System.err.
GLFWErrorCallback.createPrint(System.err).set();

// Initialize GLFW. Most GLFW functions will not work before doing this.
if ( !glfwInit() )
throw new IllegalStateException("Unable to initialize GLFW");

// Configure GLFW
glfwDefaultWindowHints(); // optional, the current window hints are already the default
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

// Create the window
window = glfwCreateWindow(800, 600, "Hello World!", NULL, NULL);
if ( window == NULL )
throw new RuntimeException("Failed to create the GLFW window");

// Setup a key callback. It will be called every time a key is pressed, repeated or released.
glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
keyboard.sendKeyEvent(scancode, action == 1);
});

final double[] lastPos = {0, 0};
glfwSetCursorPosCallback(window, (window1, xpos, ypos) -> {
mouse.sendRelEvent(xpos - lastPos[0], ypos - lastPos[1]);

lastPos[0] = xpos;
lastPos[1] = ypos;
});

glfwSetMouseButtonCallback(window, (window1, button, action, mods) -> {
if (button == 0) {
mouse.sendRightClick(action == 1);
} else if (button == 1) {
mouse.sendLeftClick(action == 1);
}
});

// Get the thread stack and push a new frame
try ( MemoryStack stack = stackPush() ) {
IntBuffer pWidth = stack.mallocInt(1); // int*
IntBuffer pHeight = stack.mallocInt(1); // int*

// Get the window size passed to glfwCreateWindow
glfwGetWindowSize(window, pWidth, pHeight);

// Get the resolution of the primary monitor
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());

// Center the window
glfwSetWindowPos(
window,
(vidmode.width() - pWidth.get(0)) / 2,
(vidmode.height() - pHeight.get(0)) / 2
);
} // the stack frame is popped automatically

// Make the OpenGL context current
glfwMakeContextCurrent(window);
// Enable v-sync
glfwSwapInterval(1);

// Make the window visible
glfwShowWindow(window);

GL.createCapabilities();
GLUtil.setupDebugMessageCallback();

glClearColor(0.1f, 0.5f, 0f, 1f);

}

public void initShaders() throws Exception {
int vertexId = glCreateShader(GL_VERTEX_SHADER);
Path vertexPath = Paths.get(getClass().getClassLoader().getResource("vertexshader.glsl").toURI());
String vertexSource = String.join("\n", Files.readAllLines(vertexPath));
glShaderSource(vertexId, vertexSource);
glCompileShader(vertexId);
String vertexInfoLog = glGetShaderInfoLog(vertexId);
if (!vertexInfoLog.isEmpty()) {
throw new Exception("Failed to compile vertex shader: " + vertexInfoLog);
}

int fragId = glCreateShader(GL_FRAGMENT_SHADER);
Path fragPath = Paths.get(getClass().getClassLoader().getResource("fragmentshader.glsl").toURI());
String fragSource = String.join("\n", Files.readAllLines(fragPath));
glShaderSource(fragId, fragSource);
glCompileShader(fragId);
String fragInfoLog = glGetShaderInfoLog(fragId);
if (!fragInfoLog.isEmpty()) {
throw new Exception("Failed to compile fragment shader: " + fragInfoLog);
}

shaderId = glCreateProgram();
glAttachShader(shaderId, vertexId);
glAttachShader(shaderId, fragId);
glLinkProgram(shaderId);

String programInfoLog = glGetProgramInfoLog(shaderId);
if (!programInfoLog.isEmpty()) {
throw new Exception("Failed to link shader program: " + programInfoLog);
}

glDetachShader(shaderId, vertexId);
glDetachShader(shaderId, fragId);

glDeleteShader(vertexId);
glDeleteShader(fragId);
}

public void initBuffers() {
vao = glGenVertexArrays();
glBindVertexArray(vao);
float[] vertices = new float[] {
-1, 1, 0,
1, 1, 0,
1, -1, 0,

1, -1, 0,
-1, -1, 0,
-1, 1, 0
};

vertexBuffer = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);

float[] uvs = new float[] {
0, 0,
1, 0,
1, 1,

1, 1,
0, 1,
0, 0,
};

uvBuffer = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, uvBuffer);
glBufferData(GL_ARRAY_BUFFER, uvs, GL_STATIC_DRAW);

texture = glGenTextures();
glBindTexture(GL_TEXTURE_2D, texture);
//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
ByteBuffer buffer = BufferUtils.createByteBuffer(1024 * 1024 * 3 * 4);

glBindTexture(GL_TEXTURE_2D, texture);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1024, 1024, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
}

public void loop() {
while (true) {
if (!updateBuffer.isEmpty()) {
Pair<VirtIOGPURect, ByteBuffer> updateRequest = updateBuffer.poll();
ByteBuffer buffer = updateRequest.getValue();
if (!buffer.isDirect()) {
ByteBuffer directBuffer = ByteBuffer.allocateDirect(buffer.capacity());
directBuffer.put(buffer);
directBuffer.flip();
buffer = directBuffer;
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 800, 600, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
}

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glUseProgram(shaderId);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);

int textureId = glGetUniformLocation(shaderId, "myTextureSampler");
glUniform1i(textureId, 0);

glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, NULL);

glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, uvBuffer);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, NULL);

glDrawArrays(GL_TRIANGLES, 0, 6);

glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);


glfwSwapBuffers(window);
glfwPollEvents();
}
}

public void flush(VirtIOGPURect rect, ByteBuffer buffer) {
updateBuffer.add(new Pair<>(rect, buffer));
}
}
Binary file added Image
Binary file not shown.
Binary file added fw_jump.bin
Binary file not shown.
Binary file added fw_payload.bin
Binary file not shown.
File renamed without changes.
Binary file added rootfs.ext2
Binary file not shown.
95 changes: 95 additions & 0 deletions src/main/java/GPUResourcesViewer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import li.cil.sedna.device.virtio.gpu.VirtIOGPUDevice;
import li.cil.sedna.device.virtio.gpu.VirtIOGPUResource;
import li.cil.sedna.api.memory.MemoryAccessException;

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.Collection;
import java.util.Enumeration;

class PreviewPanel extends JPanel {
private VirtIOGPUResource resource;

@Override
public void paint(Graphics g) {
if (resource == null) {
return;
}

g.clearRect(0, 0, getWidth(), getHeight());
ByteBuffer dst = null;
try {
dst = resource.getPages().getAsByteBuffer();
} catch (MemoryAccessException e) {
e.printStackTrace();
}
BufferedImage image = new BufferedImage(resource.getWidth(), resource.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
IntBuffer intBuffer = IntBuffer.allocate(dst.capacity());
while (dst.hasRemaining()) {
intBuffer.put((dst.get() << 16 | dst.get() << 8 | dst.get()));
dst.get();
}
image.setRGB(0, 0, resource.getWidth(), resource.getHeight(), intBuffer.array(), 0, resource.getWidth());
g.drawImage(image, 0, 0, resource.getWidth(), resource.getHeight(), null);
}

public void setResource(VirtIOGPUResource o) {
this.resource = o;
repaint();
}
}

public class GPUResourcesViewer extends JFrame {
private VirtIOGPUDevice gpu;
private DefaultListModel<VirtIOGPUResource> resourcesListModel = new DefaultListModel<>();
private PreviewPanel preview = new PreviewPanel();

public GPUResourcesViewer(VirtIOGPUDevice gpu) {
this.gpu = gpu;

setLayout(new BorderLayout());
final JList<VirtIOGPUResource> resourcesList = new JList<>();
resourcesList.setModel(resourcesListModel);
add(resourcesList, BorderLayout.WEST);
resourcesList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
resourcesList.addListSelectionListener(e -> {
preview.setResource((VirtIOGPUResource) gpu.getResources().values().toArray()[e.getFirstIndex()]);
});
add(preview, BorderLayout.CENTER);

setSize(1280, 720);

new Thread(() -> {
while (true) {
Collection<VirtIOGPUResource> resources = gpu.getResources().values();
resources.forEach(resource -> {
if (!resourcesListModel.contains(resource)) {
resourcesListModel.addElement(resource);
}
});

Enumeration<VirtIOGPUResource> elements = resourcesListModel.elements();
while (elements.hasMoreElements()) {
VirtIOGPUResource element = elements.nextElement();
if (!resources.contains(element)) {
resourcesListModel.removeElement(element);
}
}

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

preview.repaint();
}
}).start();

setVisible(true);
setLocationRelativeTo(null);
}
}
Loading

0 comments on commit 2727f8a

Please sign in to comment.