Skip to content

Commit f9eff8a

Browse files
committed
Vulkan surface integration and refactor window management
1 parent f3438e1 commit f9eff8a

21 files changed

Lines changed: 1238 additions & 36 deletions

build.sbt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ lazy val utility = (project in file("cyfra-utility"))
6666
lazy val vulkan = (project in file("cyfra-vulkan"))
6767
.settings(commonSettings)
6868
.dependsOn(utility)
69+
.settings(
70+
libraryDependencies ++= Seq(
71+
"org.lwjgl" % "lwjgl-glfw" % lwjglVersion,
72+
"org.lwjgl" % "lwjgl-glfw" % lwjglVersion classifier lwjglNatives
73+
)
74+
)
6975

7076
lazy val dsl = (project in file("cyfra-dsl"))
7177
.settings(commonSettings)
@@ -101,7 +107,8 @@ lazy val rtrp = (project in file("cyfra-rtrp"))
101107
.settings(
102108
libraryDependencies ++= Seq(
103109
"org.lwjgl" % "lwjgl-glfw" % lwjglVersion,
104-
"org.lwjgl" % "lwjgl-glfw" % lwjglVersion classifier lwjglNatives
110+
"org.lwjgl" % "lwjgl-glfw" % lwjglVersion classifier lwjglNatives,
111+
"org.scalatest" %% "scalatest" % "3.2.15" % Test
105112
)
106113
)
107114

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
package io.computenode.cyfra.rtrp.surface
2+
3+
import io.computenode.cyfra.rtrp.window.WindowManager
4+
import io.computenode.cyfra.rtrp.window.core.WindowConfig
5+
import io.computenode.cyfra.rtrp.window.core.WindowPosition
6+
import io.computenode.cyfra.rtrp.surface.core.{SurfaceConfig, PresentMode}
7+
import io.computenode.cyfra.vulkan.VulkanContext
8+
import scala.util.{Try, Success, Failure}
9+
10+
// Complete example demonstrating the integrated window + surface system.
11+
object SurfaceIntegrationExample {
12+
13+
def main(args: Array[String]): Unit = {
14+
println("=== Cyfra Surface Integration Example ===")
15+
16+
val result = runFullExample()
17+
18+
result match {
19+
case Success(_) =>
20+
println("Surface integration example completed successfully!")
21+
case Failure(ex) =>
22+
println(s"Surface integration example failed: ${ex.getMessage}")
23+
ex.printStackTrace()
24+
}
25+
}
26+
27+
private def runFullExample(): Try[Unit] = Try {
28+
println("=== Cyfra Surface Integration Example ===\n")
29+
30+
// Initialize GLFW first
31+
import org.lwjgl.glfw.GLFW
32+
if (!GLFW.glfwInit()) {
33+
throw new RuntimeException("Failed to initialize GLFW")
34+
}
35+
36+
try {
37+
// Now create VulkanContext with surface support
38+
val vulkanContext = VulkanContext.withSurfaceSupport()
39+
40+
WindowManager.withVulkanManager(vulkanContext) { manager =>
41+
Try {
42+
setupEventHandlers(manager)
43+
println("Event handlers configured\n")
44+
45+
val windowsAndSurfaces = createTestWindows(manager)
46+
println(s"Created ${windowsAndSurfaces.size} window-surface pairs\n")
47+
48+
inspectSurfaceCapabilities(windowsAndSurfaces)
49+
50+
runMainLoop(manager, windowsAndSurfaces)
51+
println("Main loop completed\n")
52+
53+
windowsAndSurfaces.foreach { case (window, surface) =>
54+
testSurfaceRecreation(manager, surface)
55+
}
56+
}
57+
}
58+
} finally {
59+
GLFW.glfwTerminate()
60+
}
61+
}
62+
63+
private def setupEventHandlers(manager: WindowManager): Unit = {
64+
// Window event handlers
65+
manager.onWindowResize { event =>
66+
println(s"Window ${event.windowId} resized to ${event.width}x${event.height}")
67+
}
68+
69+
manager.onWindowClose { event =>
70+
println(s"Window ${event.windowId} close requested")
71+
}
72+
73+
manager.onKeyPress { event =>
74+
println(s"Key ${event.key.code} pressed in window ${event.windowId}")
75+
}
76+
77+
manager.onMouseClick { event =>
78+
println(s"Mouse button ${event.button.code} clicked at (${event.x.toInt}, ${event.y.toInt}) in window ${event.windowId}")
79+
}
80+
81+
// Surface event handlers
82+
manager.onSurfaceCreated { event =>
83+
println(s"Surface ${event.surfaceId} created for window ${event.windowId}")
84+
val caps = event.capabilities
85+
println(s"Formats: ${caps.supportedFormats.size}, Present modes: ${caps.supportedPresentModes.size}")
86+
}
87+
88+
manager.onSurfaceDestroyed { event =>
89+
println(s"Surface ${event.surfaceId} destroyed for window ${event.windowId}")
90+
}
91+
92+
manager.onSurfaceLost { event =>
93+
println(s"Surface ${event.surfaceId} lost for window ${event.windowId}: ${event.error}")
94+
}
95+
}
96+
97+
private def createTestWindows(manager: WindowManager): List[(io.computenode.cyfra.rtrp.window.core.Window, io.computenode.cyfra.rtrp.surface.core.RenderSurface)] = {
98+
val configs = List(
99+
// Main window - gaming configuration
100+
(WindowConfig(
101+
width = 1024,
102+
height = 768,
103+
title = "Main Window",
104+
position = Some(WindowPosition.Centered)
105+
), SurfaceConfig.gaming),
106+
107+
// Secondary window - quality configuration
108+
(WindowConfig(
109+
width = 800,
110+
height = 600,
111+
title = "Secondary Window",
112+
position = Some(WindowPosition.Fixed(100, 100))
113+
), SurfaceConfig.quality),
114+
115+
// Tool window - low latency configuration
116+
(WindowConfig(
117+
width = 400,
118+
height = 300,
119+
title = "Tool Window",
120+
position = Some(WindowPosition.Fixed(200, 200))
121+
), SurfaceConfig.lowLatency)
122+
)
123+
124+
manager.createWindowsWithSurfaces(configs) match {
125+
case Success(pairs) => pairs
126+
case Failure(ex) =>
127+
println(s"Failed to create windows: ${ex.getMessage}")
128+
List.empty
129+
}
130+
}
131+
132+
private def inspectSurfaceCapabilities(windowSurfacePairs: List[(io.computenode.cyfra.rtrp.window.core.Window, io.computenode.cyfra.rtrp.surface.core.RenderSurface)]): Unit = {
133+
windowSurfacePairs.foreach { case (window, surface) =>
134+
println(s"\n Surface ${surface.id} (Window: ${window.properties.title}):")
135+
136+
surface.getCapabilities() match {
137+
case Success(caps) =>
138+
println(s"Current size: ${caps.currentExtent}")
139+
println(s"Size range: ${caps.minImageExtent} to ${caps.maxImageExtent}")
140+
println(s"Image count: ${caps.minImageCount} to ${caps.maxImageCount}")
141+
println(s"Formats (${caps.supportedFormats.size}): ${caps.supportedFormats.take(3).mkString(", ")}${if (caps.supportedFormats.size > 3) "..." else ""}")
142+
println(s"Present modes (${caps.supportedPresentModes.size}): ${caps.supportedPresentModes.mkString(", ")}")
143+
println(s"Alpha support: ${caps.supportsAlpha}")
144+
println(s"Transform support: ${caps.supportsTransform}")
145+
146+
case Failure(ex) =>
147+
println(s"Failed to get capabilities: ${ex.getMessage}")
148+
}
149+
}
150+
}
151+
152+
private def runMainLoop(
153+
manager: WindowManager,
154+
windowSurfacePairs: List[(io.computenode.cyfra.rtrp.window.core.Window, io.computenode.cyfra.rtrp.surface.core.RenderSurface)]
155+
): Unit = {
156+
var frameCount = 0
157+
val maxFrames = 300 // 5 seconds at 60fps
158+
val windows = windowSurfacePairs.map(_._1)
159+
val surfaces = windowSurfacePairs.map(_._2)
160+
161+
while (frameCount < maxFrames && windows.exists(!_.shouldClose)) {
162+
// Poll and handle events
163+
manager.pollAndDispatchEvents() match {
164+
case Success(_) => // Events handled successfully
165+
case Failure(ex) => println(s"Warning: Event polling failed: ${ex.getMessage}")
166+
}
167+
168+
// Simulate rendering work
169+
if (frameCount % 60 == 0) {
170+
val seconds = frameCount / 60 + 1
171+
val validSurfaces = surfaces.count(_.isValid)
172+
val openWindows = windows.count(!_.shouldClose)
173+
println(s"${seconds}s: ${openWindows} windows open, ${validSurfaces} surfaces valid")
174+
175+
// Print surface manager statistics
176+
manager.getSurfaceManager().foreach { surfMgr =>
177+
val stats = surfMgr.getStatistics()
178+
println(s"Surface stats: ${stats}")
179+
}
180+
}
181+
182+
frameCount += 1
183+
Thread.sleep(16) // ~60 FPS
184+
}
185+
186+
println("Main loop completed")
187+
}
188+
189+
private def testSurfaceRecreation(manager: WindowManager, surface: io.computenode.cyfra.rtrp.surface.core.RenderSurface): Unit = {
190+
println(s"Testing recreation of surface ${surface.id}...")
191+
192+
manager.getSurfaceManager() match {
193+
case Some(surfMgr) =>
194+
surfMgr.recreateSurface(surface.windowId, "Test recreation") match {
195+
case Success(_) =>
196+
println("Surface recreation successful")
197+
case Failure(ex) =>
198+
println(s"Surface recreation failed: ${ex.getMessage}")
199+
}
200+
case None =>
201+
println("No surface manager available")
202+
}
203+
}
204+
}

0 commit comments

Comments
 (0)