Commit e1188e24 authored by spvessel's avatar spvessel

DirectX rendering implementation.

parent b6e0411e
...@@ -268,6 +268,7 @@ tasks.withType(CppCompile::class.java).configureEach { ...@@ -268,6 +268,7 @@ tasks.withType(CppCompile::class.java).configureEach {
"-DWIN32_LEAN_AND_MEAN", "-DWIN32_LEAN_AND_MEAN",
"-DNOMINMAX", "-DNOMINMAX",
"-DSK_GAMMA_APPLY_TO_A8", "-DSK_GAMMA_APPLY_TO_A8",
"-DSK_DIRECT3D",
"/utf-8", "/utf-8",
"/GR-", // no-RTTI. "/GR-", // no-RTTI.
*buildType.msvcFlags *buildType.msvcFlags
...@@ -380,7 +381,10 @@ tasks.withType(LinkSharedLibrary::class.java).configureEach { ...@@ -380,7 +381,10 @@ tasks.withType(LinkSharedLibrary::class.java).configureEach {
"Dwmapi.lib", "Dwmapi.lib",
"opengl32.lib", "opengl32.lib",
"shcore.lib", "shcore.lib",
"user32.lib" "user32.lib",
"d3d12.lib",
"dxgi.lib",
"d3dcompiler.lib"
) )
) )
} }
......
#ifdef SK_DIRECT3D
#include <windows.h>
#include <jawt_md.h>
#include "GrBackendSurface.h"
#include "GrDirectContext.h"
#include "SkSurface.h"
#include "d3d/GrD3DTypes.h"
#include <d3d12sdklayers.h>
#include "d3d/GrD3DBackendContext.h"
#include <d3d12.h>
#include <dxgi1_4.h>
#define GR_D3D_CALL_ERRCHECK(X) \
do \
{ \
HRESULT result = X; \
SkASSERT(SUCCEEDED(result)); \
if (!SUCCEEDED(result)) \
{ \
SkDebugf("Failed Direct3D call. Error: 0x%08x\n", result); \
} \
} while (false)
extern "C" jboolean Skiko_GetAWT(JNIEnv *env, JAWT *awt);
class DirectXDevice
{
public:
GrD3DBackendContext backendContext;
gr_cp<ID3D12Device> device;
gr_cp<IDXGISwapChain3> swapChain;
gr_cp<ID3D12CommandQueue> queue;
gr_cp<ID3D12Fence> fence;
HANDLE fenceEvent;
uint64_t fenceValue;
unsigned int bufferIndex = 1;
unsigned int bufferWidth = 0;
unsigned int bufferHeight = 0;
bool isSizeEqualTo(unsigned int width, unsigned int height)
{
return width == bufferWidth && height == bufferHeight;
}
};
extern "C"
{
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_makeDirectXContext(
JNIEnv* env, jobject redrawer, jlong devicePtr)
{
DirectXDevice *d3dDevice = reinterpret_cast<DirectXDevice *>(static_cast<uintptr_t>(devicePtr));
GrD3DBackendContext backendContext = d3dDevice->backendContext;
return reinterpret_cast<jlong>(GrDirectContext::MakeDirect3D(backendContext).release());
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_makeDirectXRenderTarget(
JNIEnv * env, jobject redrawer, jlong devicePtr, jint width, jint height)
{
DirectXDevice *d3dDevice = reinterpret_cast<DirectXDevice *>(static_cast<uintptr_t>(devicePtr));
d3dDevice->bufferIndex = d3dDevice->swapChain->GetCurrentBackBufferIndex();
ID3D12Resource* buffer;
GR_D3D_CALL_ERRCHECK(d3dDevice->swapChain->GetBuffer(d3dDevice->bufferIndex, IID_PPV_ARGS(&buffer)));
GrD3DTextureResourceInfo info(buffer,
nullptr,
D3D12_RESOURCE_STATE_PRESENT,
DXGI_FORMAT_R8G8B8A8_UNORM,
1,
1,
0);
GrBackendRenderTarget* renderTarget = new GrBackendRenderTarget(width, height, info);
return reinterpret_cast<jlong>(renderTarget);
}
void defineHardwareAdapter(IDXGIFactory4 *pFactory, IDXGIAdapter1 **ppAdapter)
{
*ppAdapter = nullptr;
for (UINT adapterIndex = 0;; ++adapterIndex)
{
IDXGIAdapter1 *pAdapter = nullptr;
if (DXGI_ERROR_NOT_FOUND == pFactory->EnumAdapters1(adapterIndex, &pAdapter))
{
break;
}
if (SUCCEEDED(D3D12CreateDevice(pAdapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr)))
{
*ppAdapter = pAdapter;
return;
}
pAdapter->Release();
}
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_createDevice(
JNIEnv *env, jobject redrawer)
{
DirectXDevice *d3dDevice = new DirectXDevice();
gr_cp<IDXGIFactory4> factory;
if (!SUCCEEDED(CreateDXGIFactory1(IID_PPV_ARGS(&factory))))
{
return false;
}
gr_cp<IDXGIAdapter1> hardwareAdapter;
defineHardwareAdapter(factory.get(), &hardwareAdapter);
gr_cp<ID3D12Device> device;
if (!SUCCEEDED(D3D12CreateDevice(hardwareAdapter.get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device))))
{
return false;
}
// Create the command queue
gr_cp<ID3D12CommandQueue> queue;
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
if (!SUCCEEDED(device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&queue))))
{
return false;
}
d3dDevice->backendContext.fAdapter = hardwareAdapter;
d3dDevice->backendContext.fDevice = device;
d3dDevice->backendContext.fQueue = queue;
d3dDevice->device = device;
d3dDevice->queue = queue;
return reinterpret_cast<jlong>(d3dDevice);
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_createSwapChain(
JNIEnv *env, jobject redrawer, jlong windowHandle, jlong devicePtr)
{
DirectXDevice *d3dDevice = reinterpret_cast<DirectXDevice *>(static_cast<uintptr_t>(devicePtr));
// Make the swapchain
HWND fWindow = (HWND)windowHandle;
gr_cp<IDXGIFactory4> factory;
GR_D3D_CALL_ERRCHECK(CreateDXGIFactory2(0, IID_PPV_ARGS(&factory)));
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
swapChainDesc.BufferCount = 2;
swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
swapChainDesc.SampleDesc.Count = 1;
DXGI_SWAP_CHAIN_FULLSCREEN_DESC swapChainFSDesc = {};
swapChainFSDesc.Windowed = TRUE;
gr_cp<IDXGISwapChain1> swapChain;
GR_D3D_CALL_ERRCHECK(factory->CreateSwapChainForHwnd(d3dDevice->queue.get(), fWindow, &swapChainDesc, &swapChainFSDesc, nullptr, &swapChain));
GR_D3D_CALL_ERRCHECK(swapChain->QueryInterface(IID_PPV_ARGS(&d3dDevice->swapChain)));
GR_D3D_CALL_ERRCHECK(d3dDevice->device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&d3dDevice->fence)));
d3dDevice->fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_resizeBuffers(
JNIEnv *env, jobject redrawer, jlong devicePtr, jint width, jint height)
{
DirectXDevice *d3dDevice = reinterpret_cast<DirectXDevice *>(static_cast<uintptr_t>(devicePtr));
if (!d3dDevice->isSizeEqualTo(width, height))
{
GR_D3D_CALL_ERRCHECK(d3dDevice->swapChain->ResizeBuffers(2, width, height, DXGI_FORMAT_R8G8B8A8_UNORM, 0));
d3dDevice->bufferWidth = width;
d3dDevice->bufferHeight = height;
}
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_finishFrame(
JNIEnv *env, jobject redrawer, jlong devicePtr, jlong contextPtr, jlong surfacePtr)
{
DirectXDevice *d3dDevice = reinterpret_cast<DirectXDevice *>(static_cast<uintptr_t>(devicePtr));
SkSurface *surface = reinterpret_cast<SkSurface *>(static_cast<uintptr_t>(surfacePtr));
surface->flushAndSubmit();
GrDirectContext *fContext = reinterpret_cast<GrDirectContext *>(static_cast<uintptr_t>(contextPtr));
surface->flush(SkSurface::BackendSurfaceAccess::kPresent, GrFlushInfo());
fContext->flush({});
fContext->submit(true);
GR_D3D_CALL_ERRCHECK(d3dDevice->swapChain->Present(1, 0));
const UINT64 fence = d3dDevice->fenceValue;
GR_D3D_CALL_ERRCHECK(d3dDevice->queue->Signal(d3dDevice->fence.get(), fence));
d3dDevice->fenceValue++;
if (d3dDevice->fence->GetCompletedValue() < fence)
{
GR_D3D_CALL_ERRCHECK(d3dDevice->fence->SetEventOnCompletion(fence, d3dDevice->fenceEvent));
WaitForSingleObjectEx(d3dDevice->fenceEvent, INFINITE, FALSE);
}
}
}
#endif
...@@ -3,9 +3,10 @@ package org.jetbrains.skiko ...@@ -3,9 +3,10 @@ package org.jetbrains.skiko
import org.jetbrains.skiko.SkikoProperties.renderApi import org.jetbrains.skiko.SkikoProperties.renderApi
import org.jetbrains.skiko.redrawer.LinuxOpenGLRedrawer import org.jetbrains.skiko.redrawer.LinuxOpenGLRedrawer
import org.jetbrains.skiko.redrawer.MacOsOpenGLRedrawer import org.jetbrains.skiko.redrawer.MacOsOpenGLRedrawer
import org.jetbrains.skiko.redrawer.RasterRedrawer import org.jetbrains.skiko.redrawer.SoftwareRedrawer
import org.jetbrains.skiko.redrawer.Redrawer import org.jetbrains.skiko.redrawer.Redrawer
import org.jetbrains.skiko.redrawer.WindowsOpenGLRedrawer import org.jetbrains.skiko.redrawer.WindowsOpenGLRedrawer
import org.jetbrains.skiko.redrawer.Direct3DRedrawer
import java.awt.Component import java.awt.Component
import java.awt.Window import java.awt.Window
import javax.swing.SwingUtilities import javax.swing.SwingUtilities
...@@ -33,7 +34,7 @@ internal val platformOperations: PlatformOperations by lazy { ...@@ -33,7 +34,7 @@ internal val platformOperations: PlatformOperations by lazy {
} }
override fun createRedrawer(layer: HardwareLayer) = when(renderApi) { override fun createRedrawer(layer: HardwareLayer) = when(renderApi) {
GraphicsApi.SOFTWARE -> RasterRedrawer(layer) GraphicsApi.SOFTWARE -> SoftwareRedrawer(layer)
else -> MacOsOpenGLRedrawer(layer) else -> MacOsOpenGLRedrawer(layer)
} }
} }
...@@ -56,7 +57,8 @@ internal val platformOperations: PlatformOperations by lazy { ...@@ -56,7 +57,8 @@ internal val platformOperations: PlatformOperations by lazy {
} }
override fun createRedrawer(layer: HardwareLayer) = when(renderApi) { override fun createRedrawer(layer: HardwareLayer) = when(renderApi) {
GraphicsApi.SOFTWARE -> RasterRedrawer(layer) GraphicsApi.SOFTWARE -> SoftwareRedrawer(layer)
GraphicsApi.DIRECT3D -> Direct3DRedrawer(layer)
else -> WindowsOpenGLRedrawer(layer) else -> WindowsOpenGLRedrawer(layer)
} }
} }
...@@ -92,7 +94,7 @@ internal val platformOperations: PlatformOperations by lazy { ...@@ -92,7 +94,7 @@ internal val platformOperations: PlatformOperations by lazy {
} }
override fun createRedrawer(layer: HardwareLayer) = when(renderApi) { override fun createRedrawer(layer: HardwareLayer) = when(renderApi) {
GraphicsApi.SOFTWARE -> RasterRedrawer(layer) GraphicsApi.SOFTWARE -> SoftwareRedrawer(layer)
else -> LinuxOpenGLRedrawer(layer) else -> LinuxOpenGLRedrawer(layer)
} }
} }
......
...@@ -7,7 +7,7 @@ import org.jetbrains.skija.PictureRecorder ...@@ -7,7 +7,7 @@ import org.jetbrains.skija.PictureRecorder
import org.jetbrains.skija.Rect import org.jetbrains.skija.Rect
import org.jetbrains.skiko.context.SoftwareContextHandler import org.jetbrains.skiko.context.SoftwareContextHandler
import org.jetbrains.skiko.context.createContextHandler import org.jetbrains.skiko.context.createContextHandler
import org.jetbrains.skiko.redrawer.RasterRedrawer import org.jetbrains.skiko.redrawer.SoftwareRedrawer
import org.jetbrains.skiko.redrawer.Redrawer import org.jetbrains.skiko.redrawer.Redrawer
import java.awt.Graphics import java.awt.Graphics
import javax.swing.SwingUtilities.isEventDispatchThread import javax.swing.SwingUtilities.isEventDispatchThread
...@@ -22,7 +22,7 @@ open class SkiaLayer : HardwareLayer() { ...@@ -22,7 +22,7 @@ open class SkiaLayer : HardwareLayer() {
var renderer: SkiaRenderer? = null var renderer: SkiaRenderer? = null
val clipComponents = mutableListOf<ClipRectangle>() val clipComponents = mutableListOf<ClipRectangle>()
internal var skijaState = createContextHandler(this) private var contextHandler = createContextHandler(this)
@Volatile @Volatile
private var isDisposed = false private var isDisposed = false
...@@ -102,8 +102,8 @@ open class SkiaLayer : HardwareLayer() { ...@@ -102,8 +102,8 @@ open class SkiaLayer : HardwareLayer() {
override fun draw() { override fun draw() {
check(!isDisposed) check(!isDisposed)
skijaState.apply { contextHandler.apply {
if (!initContext()) { if (!initContext(redrawer!!)) {
fallbackToRaster() fallbackToRaster()
return return
} }
...@@ -136,8 +136,8 @@ open class SkiaLayer : HardwareLayer() { ...@@ -136,8 +136,8 @@ open class SkiaLayer : HardwareLayer() {
private fun fallbackToRaster() { private fun fallbackToRaster() {
println("Falling back to software rendering...") println("Falling back to software rendering...")
redrawer?.dispose() redrawer?.dispose()
skijaState = SoftwareContextHandler(this) contextHandler = SoftwareContextHandler(this)
redrawer = RasterRedrawer(this) redrawer = SoftwareRedrawer(this)
needRedraw() needRedraw()
} }
} }
...@@ -29,7 +29,21 @@ internal object SkikoProperties { ...@@ -29,7 +29,21 @@ internal object SkikoProperties {
when(text) { when(text) {
"SOFTWARE" -> return GraphicsApi.SOFTWARE "SOFTWARE" -> return GraphicsApi.SOFTWARE
"OPENGL" -> return GraphicsApi.OPENGL "OPENGL" -> return GraphicsApi.OPENGL
else -> return GraphicsApi.OPENGL "DIRECT3D" -> {
return if (hostOs == OS.Windows) GraphicsApi.DIRECT3D else bestRenderApiForCurrentOS()
}
"METAL" -> {
return if (hostOs == OS.MacOS) GraphicsApi.METAL else bestRenderApiForCurrentOS()
}
else -> return bestRenderApiForCurrentOS()
}
}
private fun bestRenderApiForCurrentOS(): GraphicsApi {
when(hostOs) {
OS.MacOS -> return GraphicsApi.OPENGL
OS.Linux -> return GraphicsApi.OPENGL
OS.Windows -> return GraphicsApi.DIRECT3D
} }
} }
......
...@@ -10,11 +10,13 @@ import org.jetbrains.skiko.HardwareLayer ...@@ -10,11 +10,13 @@ import org.jetbrains.skiko.HardwareLayer
import org.jetbrains.skiko.OS import org.jetbrains.skiko.OS
import org.jetbrains.skiko.SkikoProperties import org.jetbrains.skiko.SkikoProperties
import org.jetbrains.skiko.hostOs import org.jetbrains.skiko.hostOs
import org.jetbrains.skiko.redrawer.Redrawer
internal fun createContextHandler(layer: HardwareLayer): ContextHandler { internal fun createContextHandler(layer: HardwareLayer): ContextHandler {
return when (SkikoProperties.renderApi) { return when (SkikoProperties.renderApi) {
GraphicsApi.SOFTWARE -> SoftwareContextHandler(layer) GraphicsApi.SOFTWARE -> SoftwareContextHandler(layer)
GraphicsApi.OPENGL -> OpenGLContextHandler(layer) GraphicsApi.OPENGL -> OpenGLContextHandler(layer)
GraphicsApi.DIRECT3D -> Direct3DContextHandler(layer)
else -> TODO("Unsupported yet") else -> TODO("Unsupported yet")
} }
} }
...@@ -26,7 +28,7 @@ internal abstract class ContextHandler(val layer: HardwareLayer) { ...@@ -26,7 +28,7 @@ internal abstract class ContextHandler(val layer: HardwareLayer) {
var surface: Surface? = null var surface: Surface? = null
var canvas: Canvas? = null var canvas: Canvas? = null
abstract fun initContext(): Boolean abstract fun initContext(redrawer: Redrawer): Boolean
abstract fun initCanvas() abstract fun initCanvas()
......
package org.jetbrains.skiko.context
import org.jetbrains.skija.ColorSpace
import org.jetbrains.skija.FramebufferFormat
import org.jetbrains.skija.Picture
import org.jetbrains.skija.Surface
import org.jetbrains.skija.SurfaceColorFormat
import org.jetbrains.skija.SurfaceOrigin
import org.jetbrains.skija.impl.Native
import org.jetbrains.skiko.HardwareLayer
import org.jetbrains.skiko.SkiaLayer
import org.jetbrains.skiko.redrawer.Direct3DRedrawer
import org.jetbrains.skiko.redrawer.Redrawer
internal class Direct3DContextHandler(layer: HardwareLayer) : ContextHandler(layer) {
lateinit var directXRedrawer: Direct3DRedrawer
var device: Long = 0
override fun initContext(redrawer: Redrawer): Boolean {
try {
if (!this::directXRedrawer.isInitialized) {
directXRedrawer = redrawer as Direct3DRedrawer
}
if (context == null) {
device = directXRedrawer.createDevice()
directXRedrawer.createSwapChain(layer.windowHandle, device)
context = directXRedrawer.makeContext(device)
}
} catch (e: Exception) {
println("Failed to create Skia Direct3D context!\n ${e.stackTrace}")
return false
}
return true
}
override fun initCanvas() {
dispose()
val scale = layer.contentScale
val w = (layer.width * scale).toInt().coerceAtLeast(0)
val h = (layer.height * scale).toInt().coerceAtLeast(0)
directXRedrawer.resizeBuffers(device, w, h)
renderTarget = directXRedrawer.makeRenderTarget(device, w, h)
surface = Surface.makeFromBackendRenderTarget(
context!!,
renderTarget!!,
SurfaceOrigin.TOP_LEFT,
SurfaceColorFormat.RGBA_8888,
ColorSpace.getSRGB()
)
canvas = surface!!.canvas
}
override fun flush() {
directXRedrawer.finishFrame(
device,
Native.getPtr(context!!),
Native.getPtr(surface!!)
);
}
}
...@@ -8,9 +8,10 @@ import org.jetbrains.skiko.GraphicsApi ...@@ -8,9 +8,10 @@ import org.jetbrains.skiko.GraphicsApi
import org.jetbrains.skiko.HardwareLayer import org.jetbrains.skiko.HardwareLayer
import org.jetbrains.skiko.makeMetalContext import org.jetbrains.skiko.makeMetalContext
import org.jetbrains.skiko.makeMetalRenderTarget import org.jetbrains.skiko.makeMetalRenderTarget
import org.jetbrains.skiko.redrawer.Redrawer
internal class MetalContextHandler(layer: HardwareLayer) : ContextHandler(layer) { internal class MetalContextHandler(layer: HardwareLayer) : ContextHandler(layer) {
override fun initContext(): Boolean { override fun initContext(redrawer: Redrawer): Boolean {
try { try {
if (context == null) { if (context == null) {
context = makeMetalContext() context = makeMetalContext()
......
...@@ -10,9 +10,10 @@ import org.jetbrains.skiko.HardwareLayer ...@@ -10,9 +10,10 @@ import org.jetbrains.skiko.HardwareLayer
import org.jetbrains.skiko.makeGLContext import org.jetbrains.skiko.makeGLContext
import org.jetbrains.skiko.makeGLRenderTarget import org.jetbrains.skiko.makeGLRenderTarget
import org.jetbrains.skiko.OpenGLApi import org.jetbrains.skiko.OpenGLApi
import org.jetbrains.skiko.redrawer.Redrawer
internal class OpenGLContextHandler(layer: HardwareLayer) : ContextHandler(layer) { internal class OpenGLContextHandler(layer: HardwareLayer) : ContextHandler(layer) {
override fun initContext(): Boolean { override fun initContext(redrawer: Redrawer): Boolean {
try { try {
if (context == null) { if (context == null) {
context = makeGLContext() context = makeGLContext()
......
...@@ -17,6 +17,7 @@ import org.jetbrains.skija.Canvas ...@@ -17,6 +17,7 @@ import org.jetbrains.skija.Canvas
import org.jetbrains.skiko.HardwareLayer import org.jetbrains.skiko.HardwareLayer
import org.jetbrains.skija.ImageInfo import org.jetbrains.skija.ImageInfo
import org.jetbrains.skija.Picture import org.jetbrains.skija.Picture
import org.jetbrains.skiko.redrawer.Redrawer
internal class SoftwareContextHandler(layer: HardwareLayer) : ContextHandler(layer) { internal class SoftwareContextHandler(layer: HardwareLayer) : ContextHandler(layer) {
override val bleachConstant = -1 // it looks like java.awt.Canvas doesn't support transparency override val bleachConstant = -1 // it looks like java.awt.Canvas doesn't support transparency
...@@ -33,7 +34,7 @@ internal class SoftwareContextHandler(layer: HardwareLayer) : ContextHandler(lay ...@@ -33,7 +34,7 @@ internal class SoftwareContextHandler(layer: HardwareLayer) : ContextHandler(lay
var imageData: ByteArray? = null var imageData: ByteArray? = null
var raster: WritableRaster? = null var raster: WritableRaster? = null
override fun initContext(): Boolean { override fun initContext(redrawer: Redrawer): Boolean {
// Raster does not need context // Raster does not need context
return true return true
} }
......
package org.jetbrains.skiko.redrawer
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.swing.Swing
import org.jetbrains.skija.BackendRenderTarget
import org.jetbrains.skija.DirectContext
import org.jetbrains.skiko.FrameDispatcher
import org.jetbrains.skiko.HardwareLayer
internal class Direct3DRedrawer(
private val layer: HardwareLayer
) : Redrawer {
private val frameDispatcher = FrameDispatcher(Dispatchers.Swing) {
layer.update(System.nanoTime())
layer.draw()
}
override fun dispose() {
frameDispatcher.cancel()
}
override fun needRedraw() {
frameDispatcher.scheduleFrame()
}
override fun redrawImmediately() {
layer.update(System.nanoTime())
layer.draw()
}
fun makeContext(device: Long) = DirectContext(
makeDirectXContext(device)
)
fun makeRenderTarget(device: Long, width: Int, height: Int) = BackendRenderTarget(
makeDirectXRenderTarget(device, width, height)
)
external fun createDevice(): Long
external fun makeDirectXContext(device: Long): Long
external fun makeDirectXRenderTarget(device: Long, width: Int, height: Int): Long
external fun createSwapChain(windowHandle: Long, device: Long)
external fun resizeBuffers(device: Long, width: Int, height: Int)
external fun finishFrame(device: Long, context: Long, surface: Long)
}
...@@ -5,7 +5,7 @@ import kotlinx.coroutines.swing.Swing ...@@ -5,7 +5,7 @@ import kotlinx.coroutines.swing.Swing
import org.jetbrains.skiko.FrameDispatcher import org.jetbrains.skiko.FrameDispatcher
import org.jetbrains.skiko.HardwareLayer import org.jetbrains.skiko.HardwareLayer
internal class RasterRedrawer( internal class SoftwareRedrawer(
private val layer: HardwareLayer private val layer: HardwareLayer
) : Redrawer { ) : Redrawer {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment