-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
22 changed files
with
919 additions
and
633 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 not shown.
Binary file not shown.
0
src/main/resources/fw_payload1.bin → fw_payload1.bin
100755 → 100644
File renamed without changes.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
Oops, something went wrong.