fix glfw thread mixing

This commit is contained in:
Bixilon 2022-06-01 00:02:32 +02:00
parent 24d6062e5d
commit 3e285ca378
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
15 changed files with 57 additions and 52 deletions

View File

@ -95,6 +95,8 @@ class RenderWindow(
private var slowRendering = profile.performance.slowRendering
lateinit var thread: Thread
private set
var renderingState = RenderingStates.RUNNING
private set(value) {
@ -128,6 +130,10 @@ class RenderWindow(
fun init(latch: CountUpAndDownLatch) {
Log.log(LogMessageType.RENDERING_LOADING) { "Creating window..." }
if (this::thread.isInitialized) {
throw IllegalStateException("Thread is already set!")
}
this.thread = Thread.currentThread()
val stopwatch = Stopwatch()
window.init(connection.profiles.rendering)
@ -209,7 +215,7 @@ class RenderWindow(
})
connection.fireEvent(ResizeWindowEvent(previousSize = Vec2i(0, 0), size = window.size))
connection.fireEvent(ResizeWindowEvent(this, previousSize = Vec2i(0, 0), size = window.size))
textureManager.dynamicTextures.activate()
textureManager.staticTextures.activate()

View File

@ -89,7 +89,7 @@ class Rendering(private val connection: PlayConnection) {
exception.printStackTrace()
try {
renderWindow.window.destroy()
connection.fireEvent(WindowCloseEvent(window = renderWindow.window))
connection.fireEvent(WindowCloseEvent(renderWindow, window = renderWindow.window))
} catch (ignored: Throwable) {
}
connection.network.disconnect()

View File

@ -15,10 +15,9 @@ package de.bixilon.minosoft.gui.rendering.modding.events
import de.bixilon.kotlinglm.mat4x4.Mat4
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.Rendering
class CameraMatrixChangeEvent(
renderWindow: RenderWindow = Rendering.currentContext!!,
renderWindow: RenderWindow,
viewMatrix: Mat4,
projectionMatrix: Mat4,
viewProjectionMatrix: Mat4,

View File

@ -15,10 +15,9 @@ package de.bixilon.minosoft.gui.rendering.modding.events
import de.bixilon.kotlinglm.vec3.Vec3
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.Rendering
class CameraPositionChangeEvent(
renderWindow: RenderWindow = Rendering.currentContext!!,
renderWindow: RenderWindow,
newPosition: Vec3,
) : RenderEvent(renderWindow) {
val newPosition: Vec3 = newPosition

View File

@ -15,10 +15,9 @@ package de.bixilon.minosoft.gui.rendering.modding.events
import de.bixilon.kotlinglm.vec2.Vec2i
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.Rendering
class ResizeWindowEvent(
renderWindow: RenderWindow = Rendering.currentContext!!,
renderWindow: RenderWindow,
val previousSize: Vec2i,
val size: Vec2i,
) : RenderEvent(renderWindow)

View File

@ -14,8 +14,7 @@
package de.bixilon.minosoft.gui.rendering.modding.events
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.Rendering
class VisibilityGraphChangeEvent(
renderWindow: RenderWindow = Rendering.currentContext!!,
renderWindow: RenderWindow,
) : RenderEvent(renderWindow)

View File

@ -1,6 +1,6 @@
/*
* Minosoft
* Copyright (C) 2021 Moritz Zwerger
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
@ -14,11 +14,10 @@
package de.bixilon.minosoft.gui.rendering.modding.events
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.Rendering
import de.bixilon.minosoft.gui.rendering.system.window.BaseWindow
import de.bixilon.minosoft.modding.event.events.CancelableEvent
class WindowCloseEvent(
renderWindow: RenderWindow = Rendering.currentContext!!,
renderWindow: RenderWindow,
val window: BaseWindow,
) : RenderEvent(renderWindow), CancelableEvent

View File

@ -1,6 +1,6 @@
/*
* Minosoft
* Copyright (C) 2021 Moritz Zwerger
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
@ -14,11 +14,10 @@
package de.bixilon.minosoft.gui.rendering.modding.events
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.Rendering
import de.bixilon.minosoft.gui.rendering.system.window.BaseWindow
class WindowFocusChangeEvent(
renderWindow: RenderWindow = Rendering.currentContext!!,
renderWindow: RenderWindow,
val window: BaseWindow,
val focused: Boolean,
) : RenderEvent(renderWindow)

View File

@ -1,6 +1,6 @@
/*
* Minosoft
* Copyright (C) 2021 Moritz Zwerger
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
@ -14,11 +14,10 @@
package de.bixilon.minosoft.gui.rendering.modding.events
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.Rendering
import de.bixilon.minosoft.gui.rendering.system.window.BaseWindow
class WindowIconifyChangeEvent(
renderWindow: RenderWindow = Rendering.currentContext!!,
renderWindow: RenderWindow,
val window: BaseWindow,
val iconified: Boolean,
) : RenderEvent(renderWindow)

View File

@ -15,11 +15,10 @@ package de.bixilon.minosoft.gui.rendering.modding.events.input
import de.bixilon.kotlinglm.vec2.Vec2d
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.Rendering
import de.bixilon.minosoft.gui.rendering.modding.events.RenderEvent
class MouseMoveEvent(
renderWindow: RenderWindow = Rendering.currentContext!!,
renderWindow: RenderWindow,
position: Vec2d,
previous: Vec2d,
delta: Vec2d,

View File

@ -15,12 +15,11 @@ package de.bixilon.minosoft.gui.rendering.modding.events.input
import de.bixilon.kotlinglm.vec2.Vec2d
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.Rendering
import de.bixilon.minosoft.gui.rendering.modding.events.RenderEvent
import de.bixilon.minosoft.modding.event.events.CancelableEvent
class MouseScrollEvent(
renderWindow: RenderWindow = Rendering.currentContext!!,
renderWindow: RenderWindow,
offset: Vec2d,
) : RenderEvent(renderWindow), CancelableEvent {
val offset: Vec2d = offset

View File

@ -1,6 +1,6 @@
/*
* Minosoft
* Copyright (C) 2021 Moritz Zwerger
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
@ -14,10 +14,9 @@
package de.bixilon.minosoft.gui.rendering.modding.events.input
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.Rendering
import de.bixilon.minosoft.gui.rendering.modding.events.RenderEvent
class RawCharInputEvent(
renderWindow: RenderWindow = Rendering.currentContext!!,
renderWindow: RenderWindow,
val char: Int,
) : RenderEvent(renderWindow)

View File

@ -1,6 +1,6 @@
/*
* Minosoft
* Copyright (C) 2021 Moritz Zwerger
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
@ -15,12 +15,11 @@ package de.bixilon.minosoft.gui.rendering.modding.events.input
import de.bixilon.minosoft.config.key.KeyCodes
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.Rendering
import de.bixilon.minosoft.gui.rendering.modding.events.RenderEvent
import de.bixilon.minosoft.gui.rendering.system.window.KeyChangeTypes
class RawKeyInputEvent(
renderWindow: RenderWindow = Rendering.currentContext!!,
renderWindow: RenderWindow,
val keyCode: KeyCodes,
val keyChangeType: KeyChangeTypes,
) : RenderEvent(renderWindow)

View File

@ -20,10 +20,8 @@ import de.bixilon.kutil.os.PlatformInfo
import de.bixilon.minosoft.config.key.KeyCodes
import de.bixilon.minosoft.config.profile.profiles.rendering.RenderingProfile
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.modding.events.ResizeWindowEvent
import de.bixilon.minosoft.gui.rendering.modding.events.WindowCloseEvent
import de.bixilon.minosoft.gui.rendering.modding.events.WindowFocusChangeEvent
import de.bixilon.minosoft.gui.rendering.modding.events.WindowIconifyChangeEvent
import de.bixilon.minosoft.gui.rendering.Rendering
import de.bixilon.minosoft.gui.rendering.modding.events.*
import de.bixilon.minosoft.gui.rendering.modding.events.input.MouseMoveEvent
import de.bixilon.minosoft.gui.rendering.modding.events.input.MouseScrollEvent
import de.bixilon.minosoft.gui.rendering.modding.events.input.RawCharInputEvent
@ -168,9 +166,6 @@ class GLFWWindow(
}
override fun init(profile: RenderingProfile) {
GLFWErrorCallback.createPrint(System.err).set()
check(glfwInit()) { "Unable to initialize GLFW" }
glfwDefaultWindowHints()
if (renderWindow.preferQuads) {
setOpenGLVersion(3, 0, false)
@ -215,12 +210,11 @@ class GLFWWindow(
glfwFreeCallbacks(window)
glfwDestroyWindow(window)
glfwTerminate()
glfwSetErrorCallback(null)!!.free()
glfwSetErrorCallback(null)?.free()
}
override fun close() {
if (eventMaster.fireEvent(WindowCloseEvent(window = this))) {
if (fireGLFWEvent(WindowCloseEvent(renderWindow, window = this))) {
return
}
@ -249,7 +243,7 @@ class GLFWWindow(
return
}
eventMaster.fireEvent(WindowFocusChangeEvent(window = this, focused = focused))
fireGLFWEvent(WindowFocusChangeEvent(renderWindow, window = this, focused = focused))
}
private fun onIconify(window: Long, iconified: Boolean) {
@ -257,14 +251,14 @@ class GLFWWindow(
return
}
eventMaster.fireEvent(WindowIconifyChangeEvent(window = this, iconified = iconified))
fireGLFWEvent(WindowIconifyChangeEvent(renderWindow, window = this, iconified = iconified))
}
private fun onClose(window: Long) {
if (window != this.window) {
return
}
val cancelled = eventMaster.fireEvent(WindowCloseEvent(window = this))
val cancelled = fireGLFWEvent(WindowCloseEvent(renderWindow, window = this))
if (cancelled) {
glfwSetWindowShouldClose(window, false)
@ -277,7 +271,7 @@ class GLFWWindow(
}
val previousSize = Vec2i(_size)
_size = Vec2i(width, height)
eventMaster.fireEvent(ResizeWindowEvent(previousSize = previousSize, size = _size))
fireGLFWEvent(ResizeWindowEvent(renderWindow, previousSize = previousSize, size = _size))
this.skipNextMouseEvent = true
}
@ -301,14 +295,14 @@ class GLFWWindow(
}
}
eventMaster.fireEvent(RawKeyInputEvent(keyCode = keyCode, keyChangeType = keyAction))
fireGLFWEvent(RawKeyInputEvent(renderWindow, keyCode = keyCode, keyChangeType = keyAction))
}
private fun charInput(windowId: Long, char: Int) {
if (windowId != window) {
return
}
eventMaster.fireEvent(RawCharInputEvent(char = char))
fireGLFWEvent(RawCharInputEvent(renderWindow, char = char))
}
private fun mouseMove(windowId: Long, x: Double, y: Double) {
@ -322,7 +316,7 @@ class GLFWWindow(
val delta = position - previous
this.mousePosition = position
if (!skipNextMouseEvent) {
eventMaster.fireEvent(MouseMoveEvent(position = position, previous = previous, delta = delta))
fireGLFWEvent(MouseMoveEvent(renderWindow, position = position, previous = previous, delta = delta))
} else {
skipNextMouseEvent = false
}
@ -333,7 +327,7 @@ class GLFWWindow(
return
}
eventMaster.fireEvent(MouseScrollEvent(offset = Vec2d(xOffset, yOffset)))
fireGLFWEvent(MouseScrollEvent(renderWindow, offset = Vec2d(xOffset, yOffset)))
}
override fun setIcon(size: Vec2i, buffer: ByteBuffer) {
@ -348,7 +342,22 @@ class GLFWWindow(
glfwSetWindowIcon(window, images)
}
private fun fireGLFWEvent(event: RenderEvent): Boolean {
// ToDo: It looks like glfwPollEvents is mixing threads. This should not happen.
if (Rendering.currentContext != event.renderWindow) {
event.renderWindow.queue += { eventMaster.fireEvent(event) }
return false
}
return eventMaster.fireEvent(event)
}
companion object {
init {
GLFWErrorCallback.createPrint(System.err).set()
check(glfwInit()) { "Unable to initialize GLFW" }
}
val KEY_CODE_MAPPING = mapOf(
GLFW_KEY_UNKNOWN to KeyCodes.KEY_UNKNOWN,
GLFW_KEY_SPACE to KeyCodes.KEY_SPACE,

View File

@ -13,9 +13,7 @@
package de.bixilon.minosoft.modding.event.master
import de.bixilon.kutil.collections.CollectionUtil.synchronizedSetOf
import de.bixilon.kutil.collections.CollectionUtil.toSynchronizedList
import de.bixilon.kutil.collections.CollectionUtil.toSynchronizedSet
import de.bixilon.kutil.concurrent.lock.simple.SimpleLock
import de.bixilon.minosoft.modding.event.EventInstantFire
import de.bixilon.minosoft.modding.event.events.CancelableEvent
@ -27,9 +25,10 @@ import java.util.*
import kotlin.reflect.full.companionObjectInstance
open class EventMaster(vararg parents: AbstractEventMaster) : AbstractEventMaster {
val parents: MutableSet<AbstractEventMaster> = synchronizedSetOf(*parents)
private val eventInvokerLock = SimpleLock()
private val parents: MutableSet<AbstractEventMaster> = mutableSetOf(*parents)
private val parentLock = SimpleLock()
private val eventInvokers: PriorityQueue<EventInvoker> = PriorityQueue()
private val eventInvokerLock = SimpleLock()
override val size: Int
get() {
@ -42,9 +41,11 @@ open class EventMaster(vararg parents: AbstractEventMaster) : AbstractEventMaste
override fun fireEvent(event: Event): Boolean {
for (parent in parents.toSynchronizedSet()) {
parentLock.acquire()
for (parent in parents) {
parent.fireEvent(event)
}
parentLock.release()
val toRemove: MutableSet<EventInvoker> = mutableSetOf()
eventInvokerLock.acquire()