Skip to content

Commit

Permalink
Split off JAWT getting into new class from win32Vk; and clean up win3…
Browse files Browse the repository at this point in the history
…2Vk class
  • Loading branch information
SWinxy committed Aug 31, 2021
1 parent 99475ec commit 6e859e0
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 40 deletions.
108 changes: 108 additions & 0 deletions src/org/lwjgl/vulkan/awt/AWT.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package org.lwjgl.vulkan.awt;

import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.system.jawt.JAWT;
import org.lwjgl.system.jawt.JAWTDrawingSurface;
import org.lwjgl.system.jawt.JAWTDrawingSurfaceInfo;

import java.awt.*;

import static org.lwjgl.system.jawt.JAWTFunctions.*;

/**
* Platform-independent implementation<sup>&#8224;</sup>.
* <p>
* &#8224; The JAWT library is initialized with different versions
* depending on the platform for some reason.
*
* @author SWinxy
* @author Kai Burjack
*/
public class AWT implements AutoCloseable {

private final JAWT jawt;
private final JAWTDrawingSurface drawingSurface;
private final JAWTDrawingSurfaceInfo drawingSurfaceInfo;

/**
* Initializes native window handlers from the desired AWT component.
* The component MUST be a {@link Component}, but should be a canvas
* or window for native rendering.
*
* @param component a component to render onto
* @throws AWTException Fails for one of the provided reasons:
* <ul>
* <li>if the JAWT library failed to initialize;</li>
* <li>if the drawing surface could not be retrieved;</li>
* <li>if JAWT failed to lock the drawing surface;</li>
* <li>or if JAWT failed to get information about the drawing surface;</li>
* </ul>
*/
public AWT(Component component) throws AWTException {
try (MemoryStack stack = MemoryStack.stackPush()) {

jawt = JAWT
.callocStack(stack)
.version(JAWT_VERSION_1_7);

// Initialize JAWT
if (!JAWT_GetAWT(jawt)) {
throw new AWTException("Failed to initialize the native JAWT library.");
}

// Get the drawing surface from the canvas
drawingSurface = JAWT_GetDrawingSurface(component, jawt.GetDrawingSurface());
if (drawingSurface == null) {
throw new AWTException("Failed to get drawing surface.");
}

// Try to lock the surface for native rendering
int lock = JAWT_DrawingSurface_Lock(drawingSurface, drawingSurface.Lock());
if ((lock & JAWT_LOCK_ERROR) != 0) {
JAWT_FreeDrawingSurface(drawingSurface, jawt.FreeDrawingSurface());
throw new AWTException("Failed to lock the AWT drawing surface.");
}

drawingSurfaceInfo = JAWT_DrawingSurface_GetDrawingSurfaceInfo(drawingSurface, drawingSurface.GetDrawingSurfaceInfo());
if (drawingSurfaceInfo == null) {
JAWT_DrawingSurface_Unlock(drawingSurface, drawingSurface.Unlock());
throw new AWTException("Failed to get AWT drawing surface information.");
}

long address = drawingSurfaceInfo.platformInfo();

if (address == MemoryUtil.NULL) {
throw new AWTException("An unknown error occurred. Failed to retrieve platform-specific information.");
}
}
}

public static AWT create(Canvas canvas) throws AWTException {
return new AWT(canvas);
}

/**
* Returns a pointer to a platform-specific struct with platform-specific information.
* <p>
* The pointer can be safely cast to a {@link org.lwjgl.system.jawt.JAWTWin32DrawingSurfaceInfo}
* or {@link org.lwjgl.system.jawt.JAWTX11DrawingSurfaceInfo} struct, or--if on MacOS--
* a pointer to an {@code NSObject}.
* <p>
* On win32 or X11 platforms, this can easily be created in Java via LWJGL's
* {@code #create(long)} method.
*
* @return pointer to platform-specific data
*/
public long getPlatformInfo() {
return drawingSurfaceInfo.platformInfo();
}

@Override
public void close() {
// Free and unlock
JAWT_DrawingSurface_FreeDrawingSurfaceInfo(drawingSurfaceInfo, drawingSurface.FreeDrawingSurfaceInfo());
JAWT_DrawingSurface_Unlock(drawingSurface, drawingSurface.Unlock());
JAWT_FreeDrawingSurface(drawingSurface, jawt.FreeDrawingSurface());
}
}
81 changes: 41 additions & 40 deletions src/org/lwjgl/vulkan/awt/PlatformWin32VKCanvas.java
Original file line number Diff line number Diff line change
@@ -1,66 +1,67 @@
package org.lwjgl.vulkan.awt;

import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.jawt.JAWT;
import org.lwjgl.system.jawt.JAWTDrawingSurface;
import org.lwjgl.system.jawt.JAWTDrawingSurfaceInfo;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.system.jawt.JAWTWin32DrawingSurfaceInfo;
import org.lwjgl.system.windows.WinBase;
import org.lwjgl.vulkan.VkPhysicalDevice;
import org.lwjgl.vulkan.VkWin32SurfaceCreateInfoKHR;

import java.awt.*;
import java.nio.ByteBuffer;
import java.nio.LongBuffer;

import static org.lwjgl.system.jawt.JAWTFunctions.*;
import static org.lwjgl.vulkan.KHRWin32Surface.*;
import static org.lwjgl.vulkan.VK10.VK_SUCCESS;
import static org.lwjgl.vulkan.VK10.*;

/**
* Window-specific implementation of {@link PlatformVKCanvas}.
*
*
* @author Kai Burjack
* @author SWinxy
*/
public class PlatformWin32VKCanvas implements PlatformVKCanvas {
private static final JAWT awt;
static {
awt = JAWT.callocStack();
awt.version(JAWT_VERSION_1_4);
if (!JAWT_GetAWT(awt))
throw new AssertionError("GetAWT failed");
}

// 3.2.3 does not include the newest VkResult code
private static final int VK_ERROR_UNKNOWN = -13;

public long create(Canvas canvas, VKData data) throws AWTException {
MemoryStack stack = MemoryStack.stackGet();
JAWTDrawingSurface ds = JAWT_GetDrawingSurface(canvas, awt.GetDrawingSurface());
try {
int lock = JAWT_DrawingSurface_Lock(ds, ds.Lock());
if ((lock & JAWT_LOCK_ERROR) != 0)
throw new AWTException("JAWT_DrawingSurface_Lock() failed");
try {
JAWTDrawingSurfaceInfo dsi = JAWT_DrawingSurface_GetDrawingSurfaceInfo(ds, ds.GetDrawingSurfaceInfo());
try {
JAWTWin32DrawingSurfaceInfo dsiWin = JAWTWin32DrawingSurfaceInfo.create(dsi.platformInfo());
long hwnd = dsiWin.hwnd();
VkWin32SurfaceCreateInfoKHR sci = VkWin32SurfaceCreateInfoKHR.callocStack(stack)
.sType(VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR)
.hinstance(WinBase.GetModuleHandle((ByteBuffer) null))
.hwnd(hwnd);
LongBuffer pSurface = stack.mallocLong(1);
int err = vkCreateWin32SurfaceKHR(data.instance, sci, null, pSurface);
if (err != VK_SUCCESS) {
throw new AWTException("Calling vkCreateWin32SurfaceKHR failed with error: " + err);
}
try (AWT awt = AWT.create(canvas)) {
try (MemoryStack stack = MemoryStack.stackPush()) {

// Get ptr to win32 struct
JAWTWin32DrawingSurfaceInfo dsiWin = JAWTWin32DrawingSurfaceInfo.create(awt.getPlatformInfo());

// Gets a handle to the file used to create the calling process (.exe file)
long handle = WinBase.nGetModuleHandle(MemoryUtil.NULL);

VkWin32SurfaceCreateInfoKHR sci = VkWin32SurfaceCreateInfoKHR.callocStack(stack)
.sType(VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR)
.hinstance(handle)
.hwnd(dsiWin.hwnd());

LongBuffer pSurface = stack.mallocLong(1);
int result = vkCreateWin32SurfaceKHR(data.instance, sci, null, pSurface);

// Possible VkResult codes returned
if (result == VK_SUCCESS) {
return pSurface.get(0);
} finally {
JAWT_DrawingSurface_FreeDrawingSurfaceInfo(dsi, ds.FreeDrawingSurfaceInfo());
}
} finally {
JAWT_DrawingSurface_Unlock(ds, ds.Unlock());
if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
throw new AWTException("Failed to create a Vulkan surface: out of host memory.");
}
if (result == VK_ERROR_OUT_OF_DEVICE_MEMORY) {
throw new AWTException("Failed to create a Vulkan surface: out of device memory.");
}

// Error unknown to the implementation
if (result == VK_ERROR_UNKNOWN) {
throw new AWTException("An unknown error occurred. This may be because of an invalid input, " +
"or because the Vulkan implementation has a bug.");
}

// Unknown error not included in this list
throw new AWTException("Calling vkCreateWin32SurfaceKHR failed with unknown Vulkan error: " + result);
}
} finally {
JAWT_FreeDrawingSurface(ds, awt.FreeDrawingSurface());
}
}

Expand Down

0 comments on commit 6e859e0

Please sign in to comment.