Unverified Commit 8ebf6920 authored by Roman Sedaikin's avatar Roman Sedaikin Committed by GitHub

Merge pull request #98 from JetBrains/resize-reinit-refactor

Resize reinit refactor
parents f038be57 9dbb64e7
......@@ -94,6 +94,21 @@ class Renderer(
val contentScale = layer.contentScale
canvas.scale(contentScale, contentScale)
displayScene(this, (width / contentScale).toInt(), (height / contentScale).toInt(), nanoTime)
// Alpha layers test
val rectW = 100f
val rectH = 100f
val left = (width - rectW) / 2f
val top = (height - rectH) / 2f
val pictureRecorder = PictureRecorder()
val pictureCanvas = pictureRecorder.beginRecording(
Rect.makeLTRB(left, top, left + rectW, top + rectH)
)
pictureCanvas.drawLine(left, top, left + rectW, top + rectH, Paint())
val picture = pictureRecorder.finishRecordingAsPicture()
canvas.drawPicture(picture, null, Paint())
canvas.drawLine(left, top + rectH, left + rectW, top, Paint())
layer.needRedraw()
}
}
......
......@@ -33,32 +33,27 @@ const int BuffersCount = 2;
// with the current Swing/Skia integration.
// If PC has other graphics cards suitable for DirectX12, one of them will be used. Otherwise,
// rendering will falls back to OpenGL.
const std::vector<std::wstring> adapterBlacklist {
const std::vector<std::wstring> adapterBlacklist{
L"Microsoft Basic Render Driver",
L"Intel(R) HD Graphics 520",
L"Intel(R) HD Graphics 530",
L"NVIDIA GeForce GTX 750 Ti",
L"NVIDIA GeForce GTX 960M",
L"NVIDIA Quadro M2000M" };
L"NVIDIA Quadro M2000M"};
class DirectXDevice
{
public:
HWND window;
GrD3DBackendContext backendContext;
gr_cp<ID3D12Device> device;
gr_cp<IDXGISwapChain3> swapChain;
gr_cp<ID3D12CommandQueue> queue;
gr_cp<ID3D12Resource> buffers[BuffersCount];
gr_cp<ID3D12Fence> fence;
uint64_t fenceValues[BuffersCount];
HANDLE fenceEvent = NULL;
uint64_t fenceValue;
unsigned int bufferIndex = 0;
unsigned int bufferWidth = 0;
unsigned int bufferHeight = 0;
bool isSizeEqualTo(unsigned int width, unsigned int height)
{
return width == bufferWidth && height == bufferHeight;
}
unsigned int bufferIndex;
~DirectXDevice()
{
......@@ -66,6 +61,10 @@ public:
{
CloseHandle(fenceEvent);
}
for (int i = 0; i < BuffersCount; i++)
{
buffers[i].reset(nullptr);
}
fence.reset(nullptr);
swapChain.reset(nullptr);
queue.reset(nullptr);
......@@ -76,20 +75,20 @@ public:
extern "C"
{
HRESULT D3D12CreateDevice(
HRESULT D3D12CreateDevice(
IUnknown *pAdapter,
D3D_FEATURE_LEVEL MinimumFeatureLevel,
REFIID riid,
void **ppDevice
) {
void **ppDevice)
{
typedef HRESULT (*D3D12CreateDevice_t)(
IUnknown *pAdapter,
IUnknown * pAdapter,
D3D_FEATURE_LEVEL MinimumFeatureLevel,
REFIID riid,
void **ppDevice
);
void **ppDevice);
static D3D12CreateDevice_t impl = nullptr;
if (!impl) {
if (!impl)
{
auto d3d12dll = LoadLibrary(TEXT("D3D12.dll"));
if (!d3d12dll)
return E_NOTIMPL;
......@@ -98,22 +97,22 @@ HRESULT D3D12CreateDevice(
return E_NOTIMPL;
}
return impl(pAdapter, MinimumFeatureLevel, riid, ppDevice);
}
}
HRESULT D3D12SerializeRootSignature(
HRESULT D3D12SerializeRootSignature(
const D3D12_ROOT_SIGNATURE_DESC *pRootSignature,
D3D_ROOT_SIGNATURE_VERSION Version,
ID3DBlob **ppBlob,
ID3DBlob **ppErrorBlob
) {
ID3DBlob **ppErrorBlob)
{
typedef HRESULT (*D3D12SerializeRootSignature_t)(
const D3D12_ROOT_SIGNATURE_DESC *pRootSignature,
D3D_ROOT_SIGNATURE_VERSION Version,
ID3DBlob **ppBlob,
ID3DBlob **ppErrorBlob
);
ID3DBlob **ppErrorBlob);
static D3D12SerializeRootSignature_t impl = nullptr;
if (!impl) {
if (!impl)
{
auto d3d12dll = LoadLibrary(TEXT("D3D12.dll"));
if (!d3d12dll)
return E_NOTIMPL;
......@@ -122,18 +121,18 @@ HRESULT D3D12SerializeRootSignature(
return E_NOTIMPL;
}
return impl(pRootSignature, Version, ppBlob, ppErrorBlob);
}
}
HRESULT CreateDXGIFactory1(
HRESULT CreateDXGIFactory1(
REFIID riid,
void **ppFactory
) {
void **ppFactory)
{
typedef HRESULT (*CreateDXGIFactory1_t)(
REFIID riid,
void **ppFactory
);
void **ppFactory);
static CreateDXGIFactory1_t impl = nullptr;
if (!impl) {
if (!impl)
{
auto dxgidll = LoadLibrary(TEXT("Dxgi.dll"));
if (!dxgidll)
return E_NOTIMPL;
......@@ -142,20 +141,20 @@ HRESULT CreateDXGIFactory1(
return E_NOTIMPL;
}
return impl(riid, ppFactory);
}
}
HRESULT CreateDXGIFactory2(
HRESULT CreateDXGIFactory2(
UINT Flags,
REFIID riid,
void **ppFactory
) {
void **ppFactory)
{
typedef HRESULT (*CreateDXGIFactory2_t)(
UINT Flags,
REFIID riid,
void **ppFactory
);
void **ppFactory);
static CreateDXGIFactory2_t impl = nullptr;
if (!impl) {
if (!impl)
{
auto dxgidll = LoadLibrary(TEXT("Dxgi.dll"));
if (!dxgidll)
return E_NOTIMPL;
......@@ -164,9 +163,9 @@ HRESULT CreateDXGIFactory2(
return E_NOTIMPL;
}
return impl(Flags, riid, ppFactory);
}
}
HRESULT D3DCompile(
HRESULT D3DCompile(
LPCVOID pSrcData,
SIZE_T SrcDataSize,
LPCSTR pSourceName,
......@@ -177,8 +176,8 @@ HRESULT D3DCompile(
UINT Flags1,
UINT Flags2,
ID3DBlob **ppCode,
ID3DBlob **ppErrorMsgs
) {
ID3DBlob **ppErrorMsgs)
{
typedef HRESULT (*D3DCompile_t)(
LPCVOID pSrcData,
SIZE_T SrcDataSize,
......@@ -190,10 +189,10 @@ HRESULT D3DCompile(
UINT Flags1,
UINT Flags2,
ID3DBlob **ppCode,
ID3DBlob **ppErrorMsgs
);
ID3DBlob **ppErrorMsgs);
static D3DCompile_t impl = nullptr;
if (!impl) {
if (!impl)
{
auto d3dcompilerdll = LoadLibrary(TEXT("d3dcompiler_47.dll"));
if (!d3dcompilerdll)
return E_NOTIMPL;
......@@ -202,48 +201,15 @@ HRESULT D3DCompile(
return E_NOTIMPL;
}
return impl(pSrcData, SrcDataSize, pSourceName, pDefines, pInclude, pEntrypoint, pTarget, Flags1, Flags2, ppCode, ppErrorMsgs);
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_makeDirectXContext(
JNIEnv* env, jobject redrawer, jlong devicePtr)
{
DirectXDevice *d3dDevice = fromJavaPointer<DirectXDevice*>(devicePtr);
GrD3DBackendContext backendContext = d3dDevice->backendContext;
return toJavaPointer(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 = fromJavaPointer<DirectXDevice*>(devicePtr);
if (!d3dDevice->isSizeEqualTo(width, height))
{
GR_D3D_CALL_ERRCHECK(d3dDevice->swapChain->ResizeBuffers(BuffersCount, width, height, DXGI_FORMAT_R8G8B8A8_UNORM, 0));
d3dDevice->bufferWidth = width;
d3dDevice->bufferHeight = height;
}
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 toJavaPointer(renderTarget);
}
bool isBlacklisted(IDXGIAdapter1* hardwareAdapter)
bool isBlacklisted(IDXGIAdapter1 *hardwareAdapter)
{
DXGI_ADAPTER_DESC1 desc;
hardwareAdapter->GetDesc1(&desc);
std::wstring currentAdapterName(desc.Description);
for (std::wstring name : adapterBlacklist) {
for (std::wstring name : adapterBlacklist)
{
if (currentAdapterName == name)
{
fwprintf(stderr, L"Graphics card: %s is blacklisted.\n", name.c_str());
......@@ -312,13 +278,21 @@ HRESULT D3DCompile(
d3dDevice->backendContext.fAdapter = hardwareAdapter;
d3dDevice->backendContext.fDevice = device;
d3dDevice->backendContext.fQueue = queue;
d3dDevice->backendContext.fProtectedContext = GrProtected::kNo;
d3dDevice->device = device;
d3dDevice->queue = queue;
d3dDevice->window = (HWND)windowHandle;
// Make the swapchain
HWND fWindow = (HWND)windowHandle;
return toJavaPointer(d3dDevice);
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_initSwapChain(
JNIEnv *env, jobject redrawer, jlong devicePtr)
{
DirectXDevice *d3dDevice = fromJavaPointer<DirectXDevice *>(devicePtr);
// Make the swapchain
gr_cp<IDXGIFactory4> swapChainFactory;
GR_D3D_CALL_ERRCHECK(CreateDXGIFactory2(0, IID_PPV_ARGS(&swapChainFactory)));
......@@ -326,71 +300,145 @@ HRESULT D3DCompile(
swapChainDesc.BufferCount = BuffersCount;
swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.Scaling = DXGI_SCALING_NONE;
DXGI_SWAP_CHAIN_FULLSCREEN_DESC swapChainFSDesc = {};
swapChainFSDesc.Windowed = TRUE;
gr_cp<IDXGISwapChain1> swapChain;
GR_D3D_CALL_ERRCHECK(swapChainFactory->CreateSwapChainForHwnd(d3dDevice->queue.get(), fWindow, &swapChainDesc, &swapChainFSDesc, nullptr, &swapChain));
GR_D3D_CALL_ERRCHECK(swapChainFactory->CreateSwapChainForHwnd(d3dDevice->queue.get(), d3dDevice->window, &swapChainDesc, nullptr, nullptr, &swapChain));
GR_D3D_CALL_ERRCHECK(swapChainFactory->MakeWindowAssociation(d3dDevice->window, DXGI_MWA_NO_ALT_ENTER));
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);
RECT windowRect;
GetWindowRect(d3dDevice->window, &windowRect);
unsigned int w = windowRect.right - windowRect.left;
unsigned int h = windowRect.bottom - windowRect.top;
GR_D3D_CALL_ERRCHECK(d3dDevice->swapChain->ResizeBuffers(BuffersCount, w, h, DXGI_FORMAT_R8G8B8A8_UNORM, 0));
swapChainFactory.reset(nullptr);
swapChainFactory.reset(nullptr);
}
return toJavaPointer(d3dDevice);
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_initFence(
JNIEnv *env, jobject redrawer, jlong devicePtr)
{
DirectXDevice *d3dDevice = fromJavaPointer<DirectXDevice *>(devicePtr);
for (int i = 0; i < BuffersCount; i++)
{
d3dDevice->fenceValues[i] = 10000;
}
GR_D3D_CALL_ERRCHECK(d3dDevice->device->CreateFence(d3dDevice->fenceValues[0],
D3D12_FENCE_FLAG_NONE,
IID_PPV_ARGS(&d3dDevice->fence)));
d3dDevice->fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
SkASSERT(d3dDevice->fenceEvent);
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_makeDirectXContext(
JNIEnv *env, jobject redrawer, jlong devicePtr)
{
DirectXDevice *d3dDevice = fromJavaPointer<DirectXDevice *>(devicePtr);
GrD3DBackendContext backendContext = d3dDevice->backendContext;
return toJavaPointer(GrDirectContext::MakeDirect3D(backendContext).release());
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_makeDirectXSurface(
JNIEnv *env, jobject redrawer, jlong devicePtr, jlong contextPtr, jint width, jint height, jint index)
{
DirectXDevice *d3dDevice = fromJavaPointer<DirectXDevice *>(devicePtr);
GrDirectContext *context = fromJavaPointer<GrDirectContext *>(contextPtr);
GrD3DTextureResourceInfo info(nullptr,
nullptr,
D3D12_RESOURCE_STATE_PRESENT,
DXGI_FORMAT_R8G8B8A8_UNORM,
1,
1,
0);
GR_D3D_CALL_ERRCHECK(d3dDevice->swapChain->GetBuffer(index, IID_PPV_ARGS(&d3dDevice->buffers[index])));
info.fResource = d3dDevice->buffers[index];
SkSurfaceProps surfaceProps(0, kRGB_H_SkPixelGeometry);
GrBackendTexture backendTexture((int)d3dDevice->buffers[index]->GetDesc().Width, (int)d3dDevice->buffers[index]->GetDesc().Height, info);
return toJavaPointer(SkSurface::MakeFromBackendTexture(
context, backendTexture, kTopLeft_GrSurfaceOrigin, 0,
kRGBA_8888_SkColorType, SkColorSpace::MakeSRGB(), &surfaceProps)
.release());
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_resizeBuffers(
JNIEnv *env, jobject redrawer, jlong devicePtr, jint width, jint height)
{
DirectXDevice *d3dDevice = fromJavaPointer<DirectXDevice*>(devicePtr);
if (!d3dDevice->isSizeEqualTo(width, height))
DirectXDevice *d3dDevice = fromJavaPointer<DirectXDevice *>(devicePtr);
for (int i = 0; i < BuffersCount; i++)
{
GR_D3D_CALL_ERRCHECK(d3dDevice->swapChain->ResizeBuffers(BuffersCount, width, height, DXGI_FORMAT_R8G8B8A8_UNORM, 0));
d3dDevice->bufferWidth = width;
d3dDevice->bufferHeight = height;
if (d3dDevice->fence->GetCompletedValue() < d3dDevice->fenceValues[i])
{
GR_D3D_CALL_ERRCHECK(d3dDevice->fence->SetEventOnCompletion(d3dDevice->fenceValues[i], d3dDevice->fenceEvent));
WaitForSingleObjectEx(d3dDevice->fenceEvent, INFINITE, FALSE);
}
d3dDevice->buffers[i].reset(nullptr);
}
GR_D3D_CALL_ERRCHECK(d3dDevice->swapChain->ResizeBuffers(BuffersCount, width, height, DXGI_FORMAT_R8G8B8A8_UNORM, 0));
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_finishFrame(
JNIEnv *env, jobject redrawer, jlong devicePtr, jlong contextPtr, jlong surfacePtr, jboolean isVsyncEnabled)
{
DirectXDevice *d3dDevice = fromJavaPointer<DirectXDevice*>(devicePtr);
SkSurface *surface = fromJavaPointer<SkSurface*>(surfacePtr);
GrDirectContext *fContext = fromJavaPointer<GrDirectContext*>(contextPtr);
DirectXDevice *d3dDevice = fromJavaPointer<DirectXDevice *>(devicePtr);
SkSurface *surface = fromJavaPointer<SkSurface *>(surfacePtr);
GrDirectContext *context = fromJavaPointer<GrDirectContext *>(contextPtr);
surface->flushAndSubmit();
surface->flushAndSubmit(true);
surface->flush(SkSurface::BackendSurfaceAccess::kPresent, GrFlushInfo());
fContext->flush({});
fContext->submit(true);
context->flush({});
context->submit(true);
// 1 value in [Present(1, 0)] enables vblank wait so this is how vertical sync works in DirectX.
const UINT64 fenceValue = d3dDevice->fenceValues[d3dDevice->bufferIndex];
GR_D3D_CALL_ERRCHECK(d3dDevice->swapChain->Present((int)isVsyncEnabled, 0));
GR_D3D_CALL_ERRCHECK(d3dDevice->queue->Signal(d3dDevice->fence.get(), fenceValue));
}
const UINT64 fence = d3dDevice->fenceValue;
GR_D3D_CALL_ERRCHECK(d3dDevice->queue->Signal(d3dDevice->fence.get(), fence));
d3dDevice->fenceValue++;
if (d3dDevice->fence->GetCompletedValue() < fence)
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_disposeDevice(
JNIEnv *env, jobject redrawer, jlong devicePtr, jlong contextPtr)
{
GR_D3D_CALL_ERRCHECK(d3dDevice->fence->SetEventOnCompletion(fence, d3dDevice->fenceEvent));
DirectXDevice *d3dDevice = fromJavaPointer<DirectXDevice *>(devicePtr);
GrDirectContext *context = fromJavaPointer<GrDirectContext *>(contextPtr);
context->flush({});
context->submit(true);
for (int i = 0; i < BuffersCount; i++)
{
if (d3dDevice->fence->GetCompletedValue() < d3dDevice->fenceValues[i])
{
GR_D3D_CALL_ERRCHECK(d3dDevice->fence->SetEventOnCompletion(d3dDevice->fenceValues[i], d3dDevice->fenceEvent));
WaitForSingleObjectEx(d3dDevice->fenceEvent, INFINITE, FALSE);
}
}
JNIEXPORT void JNICALL Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_disposeDevice(
delete d3dDevice;
}
JNIEXPORT jint JNICALL Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_getBufferIndex(
JNIEnv *env, jobject redrawer, jlong devicePtr)
{
DirectXDevice *d3dDevice = fromJavaPointer<DirectXDevice*>(devicePtr);
delete d3dDevice;
DirectXDevice *d3dDevice = fromJavaPointer<DirectXDevice *>(devicePtr);
const UINT64 fenceValue = d3dDevice->fenceValues[d3dDevice->bufferIndex];
d3dDevice->bufferIndex = d3dDevice->swapChain->GetCurrentBackBufferIndex();
if (d3dDevice->fence->GetCompletedValue() < fenceValue)
{
GR_D3D_CALL_ERRCHECK(d3dDevice->fence->SetEventOnCompletion(fenceValue, d3dDevice->fenceEvent));
WaitForSingleObjectEx(d3dDevice->fenceEvent, INFINITE, FALSE);
}
d3dDevice->fenceValues[d3dDevice->bufferIndex] = fenceValue + 1;
return d3dDevice->bufferIndex;
}
JNIEXPORT jstring JNICALL Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_getAdapterName(JNIEnv * env, jobject redrawer, jlong devicePtr) {
DirectXDevice *d3dDevice = fromJavaPointer<DirectXDevice*>(devicePtr);
JNIEXPORT jstring JNICALL Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_getAdapterName(JNIEnv *env, jobject redrawer, jlong devicePtr)
{
DirectXDevice *d3dDevice = fromJavaPointer<DirectXDevice *>(devicePtr);
DXGI_ADAPTER_DESC1 desc;
d3dDevice->backendContext.fAdapter->GetDesc1(&desc);
......@@ -400,8 +448,9 @@ HRESULT D3DCompile(
return result;
}
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_getAdapterMemorySize(JNIEnv * env, jobject redrawer, jlong devicePtr) {
DirectXDevice *d3dDevice = fromJavaPointer<DirectXDevice*>(devicePtr);
JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_redrawer_Direct3DRedrawer_getAdapterMemorySize(JNIEnv *env, jobject redrawer, jlong devicePtr)
{
DirectXDevice *d3dDevice = fromJavaPointer<DirectXDevice *>(devicePtr);
DXGI_ADAPTER_DESC1 desc;
d3dDevice->backendContext.fAdapter->GetDesc1(&desc);
......
......@@ -47,7 +47,7 @@ internal abstract class ContextHandler(val layer: SkiaLayer) {
destroyContext()
}
fun disposeCanvas() {
open fun disposeCanvas() {
surface?.close()
renderTarget?.close()
}
......
......@@ -10,6 +10,9 @@ import org.jetbrains.skiko.redrawer.Direct3DRedrawer
import java.lang.ref.Reference
internal class Direct3DContextHandler(layer: SkiaLayer) : ContextHandler(layer) {
private val bufferCount = 2
private var surfaces: Array<Surface?> = arrayOfNulls(bufferCount)
val directXRedrawer: Direct3DRedrawer
get() = layer.redrawer!! as Direct3DRedrawer
......@@ -22,7 +25,6 @@ internal class Direct3DContextHandler(layer: SkiaLayer) : ContextHandler(layer)
throw Exception("Failed to create DirectX12 device.")
}
context = directXRedrawer.makeContext(device)
val printDeviceEnabled = System.getProperty("skiko.hardwareInfo.enabled") == "true"
if (System.getProperty("skiko.hardwareInfo.enabled") == "true") {
println(hardwareInfo())
}
......@@ -34,28 +36,51 @@ internal class Direct3DContextHandler(layer: SkiaLayer) : ContextHandler(layer)
return true
}
override fun initCanvas() {
disposeCanvas()
private var currentWidth = 0
private var currentHeight = 0
private fun isSizeChanged(width: Int, height: Int): Boolean {
if (width != currentWidth || height != currentHeight) {
currentWidth = width
currentHeight = height
return true
}
return false
}
private var isD3DInited = false
override fun initCanvas() {
val scale = layer.contentScale
val w = (layer.width * scale).toInt().coerceAtLeast(0)
val h = (layer.height * scale).toInt().coerceAtLeast(0)
renderTarget = directXRedrawer.makeRenderTarget(device, w, h)
if (isSizeChanged(w, h)) {
disposeCanvas()
context?.flush()
surface = Surface.makeFromBackendRenderTarget(
context!!,
renderTarget!!,
SurfaceOrigin.TOP_LEFT,
SurfaceColorFormat.RGBA_8888,
ColorSpace.getSRGB()
)
if (!isD3DInited) {
directXRedrawer.initSwapChain(device)
} else {
directXRedrawer.resizeBuffers(device, w, h)
}
try {
for (bufferIndex in 0..bufferCount - 1) {
surfaces[bufferIndex] = directXRedrawer.makeSurface(device, Native.getPtr(context!!), w, h, bufferIndex)
}
} finally {
Reference.reachabilityFence(context!!)
}
if (!isD3DInited) {
isD3DInited = true
directXRedrawer.initFence(device)
}
}
surface = surfaces[directXRedrawer.getBufferIndex(device)]
canvas = surface!!.canvas
}
override fun flush() {
super.flush()
try {
directXRedrawer.finishFrame(
device,
......@@ -69,8 +94,18 @@ internal class Direct3DContextHandler(layer: SkiaLayer) : ContextHandler(layer)
}
override fun destroyContext() {
try {
directXRedrawer.disposeDevice(device, Native.getPtr(context!!))
} finally {
Reference.reachabilityFence(context!!)
}
context?.close()
directXRedrawer.disposeDevice(device)
}
override fun disposeCanvas() {
for (bufferIndex in 0..bufferCount - 1) {
surfaces[bufferIndex]?.close()
}
}
override fun hardwareInfo(): String {
......
......@@ -26,13 +26,24 @@ internal class OpenGLContextHandler(layer: SkiaLayer) : ContextHandler(layer) {
return true
}
override fun initCanvas() {
disposeCanvas()
private var currentWidth = 0
private var currentHeight = 0
private fun isSizeChanged(width: Int, height: Int): Boolean {
if (width != currentWidth || height != currentHeight) {
currentWidth = width
currentHeight = height
return true
}
return false
}
override fun initCanvas() {
val scale = layer.contentScale
val w = (layer.width * scale).toInt().coerceAtLeast(0)
val h = (layer.height * scale).toInt().coerceAtLeast(0)
if (isSizeChanged(w, h)) {
disposeCanvas()
val gl = OpenGLApi.instance
val fbId = gl.glGetIntegerv(gl.GL_DRAW_FRAMEBUFFER_BINDING)
renderTarget = makeGLRenderTarget(
......@@ -43,7 +54,6 @@ internal class OpenGLContextHandler(layer: SkiaLayer) : ContextHandler(layer) {
fbId,
FramebufferFormat.GR_GL_RGBA8
)
surface = Surface.makeFromBackendRenderTarget(
context!!,
renderTarget!!,
......@@ -51,6 +61,7 @@ internal class OpenGLContextHandler(layer: SkiaLayer) : ContextHandler(layer) {
SurfaceColorFormat.RGBA_8888,
ColorSpace.getSRGB()
)
}
canvas = surface!!.canvas
}
......
......@@ -3,7 +3,7 @@ package org.jetbrains.skiko.redrawer
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.swing.Swing
import kotlinx.coroutines.withContext
import org.jetbrains.skija.BackendRenderTarget
import org.jetbrains.skija.Surface
import org.jetbrains.skija.DirectContext
import org.jetbrains.skiko.FrameDispatcher
import org.jetbrains.skiko.SkiaLayer
......@@ -60,8 +60,8 @@ internal class Direct3DRedrawer(
makeDirectXContext(device)
)
fun makeRenderTarget(device: Long, width: Int, height: Int) = BackendRenderTarget(
makeDirectXRenderTarget(device, width, height)
fun makeSurface(device: Long, context: Long, width: Int, height: Int, index: Int) = Surface(
makeDirectXSurface(device, context, width, height, index)
)
fun createDevice(): Long = createDirectXDevice(layer.windowHandle)
......@@ -72,10 +72,13 @@ internal class Direct3DRedrawer(
external fun createDirectXDevice(windowHandle: Long): Long
external fun makeDirectXContext(device: Long): Long
external fun makeDirectXRenderTarget(device: Long, width: Int, height: Int): Long
external fun makeDirectXSurface(device: Long, context: Long, width: Int, height: Int, index: Int): Long
external fun resizeBuffers(device: Long, width: Int, height: Int)
private external fun finishFrame(device: Long, context: Long, surface: Long, isVsyncEnabled: Boolean)
external fun disposeDevice(device: Long)
external fun disposeDevice(device: Long, context: Long)
external fun getBufferIndex(device: Long): Int
external fun initSwapChain(device: Long)
external fun initFence(device: Long)
external fun getAdapterName(device: Long): String
external fun getAdapterMemorySize(device: Long): Long
}
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