Skip to content

Commit 60961a6

Browse files
authored
Update the graphics contract to support passing in a custom device (#1221)
This change updates the graphics contract such that the graphics configuration is merged into one. I found out recently that bgfx still creates a graphics device when a window is passed in. I think everyone thought that bgfx was somehow getting the graphics device from the window, but it seems this isn't possible, at least with XamlSwapChains. If someone wanted to use their own graphics device with a window (e.g., create a multi-threaded D3D device), the current contract doesn't allow this. This is the main reason for this change. Another reason is that the MSAA and premultiplied-alpha flags apply for both when there is a window and when there is not (at least for D3D11). The only time that these flags don't apply is when there is a given back buffer, but we don't currently support this.
1 parent 883ba13 commit 60961a6

File tree

46 files changed

+550
-561
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+550
-561
lines changed
Lines changed: 74 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
#include <jni.h>
2+
#include <android/native_window.h> // requires ndk r5 or newer
3+
#include <android/native_window_jni.h> // requires ndk r5 or newer
4+
#include <android/log.h>
5+
26
#include <stdlib.h>
37
#include <string.h>
48
#include <signal.h>
59
#include <time.h>
6-
#include <memory>
710
#include <optional>
8-
#include <android/native_window.h> // requires ndk r5 or newer
9-
#include <android/native_window_jni.h> // requires ndk r5 or newer
10-
#include <android/log.h>
1111

1212
#include <AndroidExtensions/Globals.h>
1313
#include <Babylon/AppRuntime.h>
@@ -26,15 +26,15 @@
2626

2727
namespace
2828
{
29-
std::unique_ptr<Babylon::Graphics::Device> g_device{};
30-
std::unique_ptr<Babylon::Graphics::DeviceUpdate> g_deviceUpdate{};
31-
std::unique_ptr<Babylon::AppRuntime> g_runtime{};
32-
std::unique_ptr<Babylon::Plugins::ChromeDevTools> g_chromeDevTools{};
33-
Babylon::Plugins::NativeInput* g_nativeInput{};
34-
std::unique_ptr<Babylon::ScriptLoader> g_scriptLoader{};
35-
std::optional<Babylon::Plugins::NativeXr> g_nativeXr{};
36-
std::unique_ptr<Babylon::Polyfills::Canvas> nativeCanvas{};
37-
bool g_isXrActive{};
29+
std::optional<Babylon::Graphics::Device> device{};
30+
std::optional<Babylon::Graphics::DeviceUpdate> deviceUpdate{};
31+
std::optional<Babylon::AppRuntime> runtime{};
32+
std::optional<Babylon::Plugins::ChromeDevTools> chromeDevTools{};
33+
std::optional<Babylon::Plugins::NativeXr> nativeXr{};
34+
Babylon::Plugins::NativeInput* nativeInput{};
35+
std::optional<Babylon::Polyfills::Canvas> nativeCanvas{};
36+
std::optional<Babylon::ScriptLoader> scriptLoader{};
37+
bool isXrActive{};
3838
}
3939

4040
extern "C"
@@ -47,26 +47,28 @@ extern "C"
4747
JNIEXPORT void JNICALL
4848
Java_BabylonNative_Wrapper_finishEngine(JNIEnv* env, jclass clazz)
4949
{
50-
if (g_device)
50+
if (device)
5151
{
52-
g_deviceUpdate->Finish();
53-
g_device->FinishRenderingCurrentFrame();
52+
deviceUpdate->Finish();
53+
device->FinishRenderingCurrentFrame();
5454
}
5555

56-
g_chromeDevTools.reset();
57-
g_nativeXr.reset();
58-
g_scriptLoader.reset();
59-
g_nativeInput = {};
60-
g_runtime.reset();
61-
g_device.reset();
56+
isXrActive = false;
6257

63-
g_isXrActive = false;
58+
scriptLoader.reset();
59+
60+
nativeInput = {};
61+
chromeDevTools.reset();
62+
nativeXr.reset();
63+
scriptLoader.reset();
64+
runtime.reset();
65+
device.reset();
6466
}
6567

6668
JNIEXPORT void JNICALL
6769
Java_BabylonNative_Wrapper_surfaceCreated(JNIEnv* env, jclass clazz, jobject surface, jobject context)
6870
{
69-
if (!g_runtime)
71+
if (!runtime)
7072
{
7173
JavaVM* javaVM{};
7274
if (env->GetJavaVM(&javaVM) != JNI_OK)
@@ -80,20 +82,20 @@ extern "C"
8082
int32_t width = ANativeWindow_getWidth(window);
8183
int32_t height = ANativeWindow_getHeight(window);
8284

83-
Babylon::Graphics::WindowConfiguration graphicsConfig{};
85+
Babylon::Graphics::Configuration graphicsConfig{};
8486
graphicsConfig.Window = window;
8587
graphicsConfig.Width = static_cast<size_t>(width);
8688
graphicsConfig.Height = static_cast<size_t>(height);
87-
g_device = Babylon::Graphics::Device::Create(graphicsConfig);
88-
g_deviceUpdate = std::make_unique<Babylon::Graphics::DeviceUpdate>(g_device->GetUpdate("update"));
89-
g_device->StartRenderingCurrentFrame();
90-
g_deviceUpdate->Start();
89+
device.emplace(graphicsConfig);
90+
deviceUpdate.emplace(device->GetUpdate("update"));
91+
device->StartRenderingCurrentFrame();
92+
deviceUpdate->Start();
9193

92-
g_runtime = std::make_unique<Babylon::AppRuntime>();
94+
runtime.emplace();
9395

94-
g_runtime->Dispatch([](Napi::Env env)
96+
runtime->Dispatch([](Napi::Env env)
9597
{
96-
g_device->AddToJavaScript(env);
98+
device->AddToJavaScript(env);
9799

98100
Babylon::Polyfills::Console::Initialize(env, [](const char* message, Babylon::Polyfills::Console::LogLevel level)
99101
{
@@ -114,48 +116,44 @@ extern "C"
114116
Babylon::Plugins::NativeEngine::Initialize(env);
115117
Babylon::Plugins::NativeOptimizations::Initialize(env);
116118

117-
g_nativeXr.emplace(Babylon::Plugins::NativeXr::Initialize(env));
118-
g_nativeXr->SetSessionStateChangedCallback([](bool isXrActive){ g_isXrActive = isXrActive; });
119+
nativeXr.emplace(Babylon::Plugins::NativeXr::Initialize(env));
120+
nativeXr->SetSessionStateChangedCallback([](bool isXrActive){ isXrActive = isXrActive; });
119121

120-
g_nativeInput = &Babylon::Plugins::NativeInput::CreateForJavaScript(env);
122+
nativeInput = &Babylon::Plugins::NativeInput::CreateForJavaScript(env);
121123

122124
Babylon::Plugins::NativeCamera::Initialize(env);
123125
Babylon::Polyfills::Window::Initialize(env);
124126

125127
Babylon::Polyfills::XMLHttpRequest::Initialize(env);
126-
nativeCanvas = std::make_unique <Babylon::Polyfills::Canvas>(Babylon::Polyfills::Canvas::Initialize(env));
128+
nativeCanvas.emplace(Babylon::Polyfills::Canvas::Initialize(env));
127129

128-
g_chromeDevTools = std::make_unique<Babylon::Plugins::ChromeDevTools>(Babylon::Plugins::ChromeDevTools::Initialize(env));
129-
if (g_chromeDevTools->SupportsInspector())
130+
chromeDevTools.emplace(Babylon::Plugins::ChromeDevTools::Initialize(env));
131+
if (chromeDevTools->SupportsInspector())
130132
{
131-
g_chromeDevTools->StartInspector(5643, "BabylonNative Playground");
133+
chromeDevTools->StartInspector(5643, "BabylonNative Playground");
132134
}
133135
});
134136

135-
g_scriptLoader = std::make_unique<Babylon::ScriptLoader>(*g_runtime);
136-
g_scriptLoader->Eval("document = {}", "");
137-
g_scriptLoader->LoadScript("app:///Scripts/ammo.js");
138-
g_scriptLoader->LoadScript("app:///Scripts/recast.js");
139-
g_scriptLoader->LoadScript("app:///Scripts/babylon.max.js");
140-
g_scriptLoader->LoadScript("app:///Scripts/babylonjs.loaders.js");
141-
g_scriptLoader->LoadScript("app:///Scripts/babylonjs.materials.js");
142-
g_scriptLoader->LoadScript("app:///Scripts/babylon.gui.js");
137+
scriptLoader.emplace(*runtime);
138+
scriptLoader->Eval("document = {}", "");
139+
scriptLoader->LoadScript("app:///Scripts/ammo.js");
140+
scriptLoader->LoadScript("app:///Scripts/recast.js");
141+
scriptLoader->LoadScript("app:///Scripts/babylon.max.js");
142+
scriptLoader->LoadScript("app:///Scripts/babylonjs.loaders.js");
143+
scriptLoader->LoadScript("app:///Scripts/babylonjs.materials.js");
144+
scriptLoader->LoadScript("app:///Scripts/babylon.gui.js");
143145
}
144146
}
145147

146148
JNIEXPORT void JNICALL
147149
Java_BabylonNative_Wrapper_surfaceChanged(JNIEnv* env, jclass clazz, jint width, jint height, jobject surface)
148150
{
149-
if (g_runtime)
151+
if (runtime)
150152
{
151-
ANativeWindow *window = ANativeWindow_fromSurface(env, surface);
152-
g_runtime->Dispatch([window, width = static_cast<size_t>(width), height = static_cast<size_t>(height)](auto env) {
153-
Babylon::Graphics::WindowConfiguration graphicsConfig{};
154-
graphicsConfig.Window = window;
155-
graphicsConfig.Width = width;
156-
graphicsConfig.Height = height;
157-
g_device->UpdateWindow(graphicsConfig);
158-
g_device->UpdateSize(width, height);
153+
ANativeWindow* window = ANativeWindow_fromSurface(env, surface);
154+
runtime->Dispatch([window, width = static_cast<size_t>(width), height = static_cast<size_t>(height)](auto) {
155+
device->UpdateWindow(window);
156+
device->UpdateSize(width, height);
159157
});
160158
}
161159
}
@@ -170,18 +168,18 @@ extern "C"
170168
Java_BabylonNative_Wrapper_activityOnPause(JNIEnv* env, jclass clazz)
171169
{
172170
android::global::Pause();
173-
if (g_runtime)
171+
if (runtime)
174172
{
175-
g_runtime->Suspend();
173+
runtime->Suspend();
176174
}
177175
}
178176

179177
JNIEXPORT void JNICALL
180178
Java_BabylonNative_Wrapper_activityOnResume(JNIEnv* env, jclass clazz)
181179
{
182-
if (g_runtime)
180+
if (runtime)
183181
{
184-
g_runtime->Resume();
182+
runtime->Resume();
185183
}
186184
android::global::Resume();
187185
}
@@ -209,70 +207,70 @@ extern "C"
209207
JNIEXPORT void JNICALL
210208
Java_BabylonNative_Wrapper_loadScript(JNIEnv* env, jclass clazz, jstring path)
211209
{
212-
if (g_scriptLoader)
210+
if (scriptLoader)
213211
{
214-
g_scriptLoader->LoadScript(env->GetStringUTFChars(path, nullptr));
212+
scriptLoader->LoadScript(env->GetStringUTFChars(path, nullptr));
215213
}
216214
}
217215

218216
JNIEXPORT void JNICALL
219217
Java_BabylonNative_Wrapper_eval(JNIEnv* env, jclass clazz, jstring source, jstring sourceURL)
220218
{
221-
if (g_runtime)
219+
if (runtime)
222220
{
223221
std::string url = env->GetStringUTFChars(sourceURL, nullptr);
224222
std::string src = env->GetStringUTFChars(source, nullptr);
225-
g_scriptLoader->Eval(std::move(src), std::move(url));
223+
scriptLoader->Eval(std::move(src), std::move(url));
226224
}
227225
}
228226

229227
JNIEXPORT void JNICALL
230228
Java_BabylonNative_Wrapper_setTouchInfo(JNIEnv* env, jclass clazz, jint pointerId, jfloat x, jfloat y, jboolean buttonAction, jint buttonValue)
231229
{
232-
if (g_nativeInput != nullptr)
230+
if (nativeInput != nullptr)
233231
{
234232
if (buttonAction)
235233
{
236234
if (buttonValue == 1)
237-
g_nativeInput->TouchDown(pointerId, x, y);
235+
nativeInput->TouchDown(pointerId, x, y);
238236
else
239-
g_nativeInput->TouchUp(pointerId, x, y);
237+
nativeInput->TouchUp(pointerId, x, y);
240238
}
241239
else {
242-
g_nativeInput->TouchMove(pointerId, x, y);
240+
nativeInput->TouchMove(pointerId, x, y);
243241
}
244242
}
245243
}
246244

247245
JNIEXPORT void JNICALL
248246
Java_BabylonNative_Wrapper_renderFrame(JNIEnv* env, jclass clazz)
249247
{
250-
if (g_device)
248+
if (device)
251249
{
252-
g_deviceUpdate->Finish();
253-
g_device->FinishRenderingCurrentFrame();
254-
g_device->StartRenderingCurrentFrame();
255-
g_deviceUpdate->Start();
250+
deviceUpdate->Finish();
251+
device->FinishRenderingCurrentFrame();
252+
device->StartRenderingCurrentFrame();
253+
deviceUpdate->Start();
256254
}
257255
}
258256

259257
JNIEXPORT void JNICALL
260258
Java_BabylonNative_Wrapper_xrSurfaceChanged(JNIEnv* env, jclass clazz, jobject surface)
261259
{
262-
if (g_nativeXr)
260+
if (nativeXr)
263261
{
264262
ANativeWindow* window{};
265263
if (surface)
266264
{
267265
window = ANativeWindow_fromSurface(env, surface);
268266
}
269-
g_nativeXr->UpdateWindow(window);
267+
nativeXr->UpdateWindow(window);
270268
}
271269
}
272270

273271
JNIEXPORT jboolean JNICALL
274272
Java_BabylonNative_Wrapper_isXRActive(JNIEnv* env, jclass clazz)
275273
{
276-
return g_isXrActive;
274+
return isXrActive;
277275
}
278276
}

Apps/Playground/UWP/App.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,11 @@ void App::Uninitialize()
171171
m_device->FinishRenderingCurrentFrame();
172172
}
173173

174-
m_chromeDevTools.reset();
175174
m_nativeInput = {};
175+
m_chromeDevTools.reset();
176+
m_nativeCanvas.reset();
176177
m_runtime.reset();
178+
m_update.reset();
177179
m_device.reset();
178180
}
179181

@@ -364,17 +366,17 @@ void App::RestartRuntime(Windows::Foundation::Rect bounds)
364366
size_t height = static_cast<size_t>(bounds.Height * m_displayScale);
365367
auto window = from_cx<winrt::Windows::Foundation::IInspectable>(CoreWindow::GetForCurrentThread());
366368

367-
Babylon::Graphics::WindowConfiguration graphicsConfig{};
369+
Babylon::Graphics::Configuration graphicsConfig{};
368370
graphicsConfig.Window = window;
369371
graphicsConfig.Width = width;
370372
graphicsConfig.Height = height;
371373
graphicsConfig.MSAASamples = 4;
372-
m_device = Babylon::Graphics::Device::Create(graphicsConfig);
373-
m_update = std::make_unique<Babylon::Graphics::DeviceUpdate>(m_device->GetUpdate("update"));
374+
m_device.emplace(graphicsConfig);
375+
m_update.emplace(m_device->GetUpdate("update"));
374376
m_device->StartRenderingCurrentFrame();
375377
m_update->Start();
376378

377-
m_runtime = std::make_unique<Babylon::AppRuntime>();
379+
m_runtime.emplace();
378380

379381
m_runtime->Dispatch([this](Napi::Env env) {
380382
m_device->AddToJavaScript(env);
@@ -383,6 +385,8 @@ void App::RestartRuntime(Windows::Foundation::Rect bounds)
383385
OutputDebugStringA(message);
384386
});
385387

388+
m_nativeCanvas.emplace(Babylon::Polyfills::Canvas::Initialize(env));
389+
386390
Babylon::Polyfills::Window::Initialize(env);
387391

388392
Babylon::Polyfills::XMLHttpRequest::Initialize(env);
@@ -391,13 +395,11 @@ void App::RestartRuntime(Windows::Foundation::Rect bounds)
391395

392396
Babylon::Plugins::NativeOptimizations::Initialize(env);
393397

394-
m_nativeCanvas = std::make_unique <Babylon::Polyfills::Canvas>(Babylon::Polyfills::Canvas::Initialize(env));
395-
396398
Babylon::Plugins::NativeXr::Initialize(env);
397399

398400
m_nativeInput = &Babylon::Plugins::NativeInput::CreateForJavaScript(env);
399401

400-
m_chromeDevTools = std::make_unique<Babylon::Plugins::ChromeDevTools>(Babylon::Plugins::ChromeDevTools::Initialize(env));
402+
m_chromeDevTools.emplace(Babylon::Plugins::ChromeDevTools::Initialize(env));
401403
if (m_chromeDevTools->SupportsInspector())
402404
{
403405
m_chromeDevTools->StartInspector(5643, "BabylonNative Playground");

Apps/Playground/UWP/App.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include <Babylon/Plugins/ChromeDevTools.h>
77
#include <Babylon/Polyfills/Canvas.h>
88

9+
#include <optional>
10+
911
// Main entry point for our app. Connects the app with the Windows shell and handles application lifecycle events.
1012
ref class App sealed : public Windows::ApplicationModel::Core::IFrameworkView
1113
{
@@ -42,12 +44,13 @@ ref class App sealed : public Windows::ApplicationModel::Core::IFrameworkView
4244

4345
void RestartRuntime(Windows::Foundation::Rect bounds);
4446

45-
std::unique_ptr<Babylon::Graphics::Device> m_device{};
46-
std::unique_ptr<Babylon::Graphics::DeviceUpdate> m_update{};
47-
std::unique_ptr<Babylon::AppRuntime> m_runtime{};
47+
std::optional<Babylon::Graphics::Device> m_device{};
48+
std::optional<Babylon::Graphics::DeviceUpdate> m_update{};
49+
std::optional<Babylon::AppRuntime> m_runtime{};
50+
std::optional<Babylon::Polyfills::Canvas> m_nativeCanvas{};
51+
std::optional<Babylon::Plugins::ChromeDevTools> m_chromeDevTools{};
4852
Babylon::Plugins::NativeInput* m_nativeInput{};
49-
std::unique_ptr<Babylon::Plugins::ChromeDevTools> m_chromeDevTools{};
50-
std::unique_ptr<Babylon::Polyfills::Canvas> m_nativeCanvas{};
53+
5154
Windows::Foundation::Collections::IVectorView<Windows::Storage::IStorageItem^>^ m_files;
5255
bool m_windowClosed;
5356
bool m_windowVisible;

0 commit comments

Comments
 (0)