mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-28 18:15:45 +08:00
fixed an issue that could cause jittery camera motion at extremely high frame rates
This commit is contained in:
parent
1df74d75d5
commit
ef2900b535
88
.efrocachemap
generated
88
.efrocachemap
generated
@ -4056,50 +4056,50 @@
|
||||
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
|
||||
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
|
||||
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
|
||||
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "3d62f18e70a8421820ed2ae8527d7d14",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "3241035738b539e94cf719674953e8fb",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "2229f735f006bef70ad1d2c08ae97fec",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "8895e3a5b262aef6102c16029359a587",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "c94700f8b6ad1ce6b5574372a289d6da",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "8e0b9a000dab93c61bd58180a1eb69db",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "d7c2c596d67d96386171cae1489d3ff8",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "f492626b4a61c4550f3a01bc8d8abd53",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "fae843a11f1f84a2bc4a266e5723adfd",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "d2724a5a94267a0d7546c8cf648e729c",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "02df04e605addd02bcfcfe64e01109e3",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "beaac64be0ae8023cce5ec0a1d4306f0",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "f1d3c2985d5f0760c72ecded41d91398",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "271b5fc80696ba6d67d02a089358b353",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "22ddbd257824f055627c16d1be1e575a",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "b6de42bf834a0b9cc25c6433d49d6dc2",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "febb196acecc041b07d0ad06430ec2d5",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "fafe18465a2dc39e6a3e2abae0557784",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "bbab03393707e902053429ce38f9986d",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "d68af9931e2adfac40e8bb147ba0383b",
|
||||
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "f3d305e647a7f77dd70a48f615cfd750",
|
||||
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "931ce8eab9859d20ad86c47d196ba62c",
|
||||
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "f3d305e647a7f77dd70a48f615cfd750",
|
||||
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "931ce8eab9859d20ad86c47d196ba62c",
|
||||
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "e80b5f536b30a23fe107852a0c2f7536",
|
||||
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "076df48013d64bc07aa59001819f8583",
|
||||
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "e80b5f536b30a23fe107852a0c2f7536",
|
||||
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "076df48013d64bc07aa59001819f8583",
|
||||
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "fcfdeb63ced9156995cf1b08ae5c861f",
|
||||
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "d82ad28301dc8e5b0ca98cf1da5d907c",
|
||||
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "fcfdeb63ced9156995cf1b08ae5c861f",
|
||||
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "d82ad28301dc8e5b0ca98cf1da5d907c",
|
||||
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "6db0247bf985f9d8c7ed85a5e5508a8b",
|
||||
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "097e17c460bf798edf61303789860596",
|
||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "14df40bc07bdde8184843d16d5ba7798",
|
||||
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "097e17c460bf798edf61303789860596",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "044195de59694aa90afb2db2a500c383",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "5669f2204fa5bf0bfac57c249dafc1d6",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "820b134e62b814066c40c9439587c945",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "76406fb75d1bc422accf3b8ad69d48e5",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "6b25bae7fd9eabaad90a2c3103bb6948",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "55bd741c876af2a7d9633dbc6a1bff45",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "188433602c168f76f83183b052852e43",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "1bf745b621bae741df16d9b604342e4b",
|
||||
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "f6aa1723e7bee0328bcd8de8eaf41844",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "6b8d5b78eae91ce978a21766f2f08829",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "3691b9d78d2b8251fc854121ed274fa7",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "0f96bd7efe76c573c52cc391824a5bdd",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "62a3f4260790c6e4e648380985b92c79",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "4800d86542ac3db78c23984002fa4f63",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "64a094f2b2c8f82b3bb9c33077192f00",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "1f33c24237a6f3fc9ba5b04c2591d9c2",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "bd832c2b4071ad0531324190ab394d3a",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "fca25dc6756546cd5166c836f74b9ff4",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "3cb2ec9e30b8b6d52ab08aaf31cdcf9e",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "d4305ad198b3e9e26edc7bada23d2b73",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "b784af9a46351b20f03a1096d13e0243",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "561a56987aced8b326db9af825de90a5",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "0eee318bf2f64a15972bde46a33427d8",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "4464bd01ba4df385634b248a68633c4d",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "f76d925131181ed178baf38a5ffd15e0",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "9228141043bb88a32adc1c7a406dfbcc",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "413169acc3e3feaf17543be1f6e242ee",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "e73509f5d2bc32ffb81800bf31f7e44b",
|
||||
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "6ce4983e76e1cc2d2803fe306d08ad58",
|
||||
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "4ea0cf78901f994215f215aebb0af1dc",
|
||||
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "6ce4983e76e1cc2d2803fe306d08ad58",
|
||||
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "4ea0cf78901f994215f215aebb0af1dc",
|
||||
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "87f651fed518cfa5ee34f820c49af72b",
|
||||
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "5f28547e33fa30904dc989a39ac2d127",
|
||||
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "87f651fed518cfa5ee34f820c49af72b",
|
||||
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "5f28547e33fa30904dc989a39ac2d127",
|
||||
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "1168b2ba42e7120d9321a900c5712cf0",
|
||||
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "d23c56d85e8ee9a07c9245e548daa39c",
|
||||
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "1168b2ba42e7120d9321a900c5712cf0",
|
||||
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "d23c56d85e8ee9a07c9245e548daa39c",
|
||||
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "0c46358e1af4384af36367a3c0768605",
|
||||
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "de83e1b384abb333f457f2c9646f810f",
|
||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "0149ef8dae7720330416846919a834e7",
|
||||
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "de83e1b384abb333f457f2c9646f810f",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "e3ad15ecc9656a1a268582b14336bed7",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "fce3fd45ed78f84592ef914450817778",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "feeb14560de0fa18d8b7654aa43534ea",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "7896041f53b6f076d032388d661413b0",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "a5b84aaf028c8b13d55d2d99f3853f5d",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "4a8387851909f5cedabb5972b397a7b1",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "53fa53d605a009a6ab592e30d45629a8",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "2988d1791814f0ec0d64914d691a100e",
|
||||
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
|
||||
"src/assets/ba_data/python/babase/_mgen/enums.py": "f8cd3af311ac63147882590123b78318",
|
||||
"src/ballistica/base/mgen/pyembed/binding_base.inc": "c81b2b1f3a14b4cd20a7b93416fe893a",
|
||||
|
||||
1
.idea/dictionaries/ericf.xml
generated
1
.idea/dictionaries/ericf.xml
generated
@ -2974,6 +2974,7 @@
|
||||
<w>templatefs</w>
|
||||
<w>tenum</w>
|
||||
<w>termcolors</w>
|
||||
<w>termenv</w>
|
||||
<w>termios</w>
|
||||
<w>testbuffer</w>
|
||||
<w>testbuild</w>
|
||||
|
||||
10
CHANGELOG.md
10
CHANGELOG.md
@ -1,4 +1,4 @@
|
||||
### 1.7.28 (build 21397, api 8, 2023-09-28)
|
||||
### 1.7.28 (build 21401, api 8, 2023-09-29)
|
||||
|
||||
- Massively cleaned up code related to rendering and window systems (OpenGL,
|
||||
SDL, etc). This code had been growing into a nasty tangle for 15 years
|
||||
@ -74,10 +74,10 @@
|
||||
- Worked to improve sanity checking on C++ RenderComponents in debug builds to
|
||||
make it easier to use and avoid sending broken commands to the renderer. Some
|
||||
specifics follow.
|
||||
- RenderComponents no longer need an explicit Submit() at the end; if one goes
|
||||
out of scope not in the submitted state it will implicitly run a submit.
|
||||
Hopefully this will encourage concise code where RenderComponents are defined
|
||||
in tight scopes.
|
||||
- RenderComponents (C++ layer) no longer need an explicit Submit() at the end;
|
||||
if one goes out of scope not in the submitted state it will implicitly run a
|
||||
submit. Hopefully this will encourage concise code where RenderComponents are
|
||||
defined in tight scopes.
|
||||
- RenderComponents now have a ScopedTransform() call which can be used to push
|
||||
and pop the transform stack based on C++ scoping instead of the old
|
||||
PushTransform/PopTransform. This should make it harder to accidentally break
|
||||
|
||||
1
ballisticakit-cmake/.idea/dictionaries/ericf.xml
generated
1
ballisticakit-cmake/.idea/dictionaries/ericf.xml
generated
@ -1754,6 +1754,7 @@
|
||||
<w>templatefs</w>
|
||||
<w>tempvec</w>
|
||||
<w>tenum</w>
|
||||
<w>termenv</w>
|
||||
<w>testbuild</w>
|
||||
<w>testclinic</w>
|
||||
<w>testint</w>
|
||||
|
||||
@ -52,7 +52,7 @@ if TYPE_CHECKING:
|
||||
|
||||
# Build number and version of the ballistica binary we expect to be
|
||||
# using.
|
||||
TARGET_BALLISTICA_BUILD = 21397
|
||||
TARGET_BALLISTICA_BUILD = 21401
|
||||
TARGET_BALLISTICA_VERSION = '1.7.28'
|
||||
|
||||
|
||||
|
||||
@ -100,75 +100,6 @@ void AppAdapter::OnAppShutdownComplete() { assert(g_base->InLogicThread()); }
|
||||
void AppAdapter::OnScreenSizeChange() { assert(g_base->InLogicThread()); }
|
||||
void AppAdapter::DoApplyAppConfig() { assert(g_base->InLogicThread()); }
|
||||
|
||||
// void AppAdapter::DrawFrame(bool during_resize) {
|
||||
// assert(g_base->InGraphicsThread());
|
||||
|
||||
// // It's possible to be asked to draw before we're ready.
|
||||
// if (!g_base->graphics_server || !g_base->graphics_server->renderer()) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// millisecs_t starttime = g_core->GetAppTimeMillisecs();
|
||||
|
||||
// // A resize-draw event means that we're drawing due to a window resize.
|
||||
// // In this case we ignore regular draw events for a short while
|
||||
// // afterwards which makes resizing smoother.
|
||||
// //
|
||||
// // FIXME: should figure out the *correct* way to handle this; I believe
|
||||
// // the underlying cause here is some sort of context contention across
|
||||
// // threads.
|
||||
// if (during_resize) {
|
||||
// last_resize_draw_event_time_ = starttime;
|
||||
// } else {
|
||||
// if (starttime - last_resize_draw_event_time_ < (1000 / 30)) {
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// g_base->graphics_server->TryRender();
|
||||
// // RunRenderUpkeepCycle();
|
||||
// }
|
||||
|
||||
// void AppAdapter::RunRenderUpkeepCycle() {
|
||||
// // This should only be firing if the OS is handling the event loop.
|
||||
// assert(!ManagesMainThreadEventLoop());
|
||||
|
||||
// // Pump the main event loop (when we're being driven by frame-draw
|
||||
// // callbacks, this is the only place that gets done).
|
||||
// g_core->main_event_loop()->RunSingleCycle();
|
||||
|
||||
// // Now do the general app event cycle for whoever needs to process things.
|
||||
// // FIXME KILL THIS.
|
||||
// RunEvents();
|
||||
// }
|
||||
|
||||
// FIXME KILL THIS.
|
||||
// void AppAdapter::RunEvents() {
|
||||
// There's probably a better place for this.
|
||||
// g_base->stress_test()->Update();
|
||||
|
||||
// Give platforms a chance to pump/handle their own events.
|
||||
//
|
||||
// FIXME: now that we have app class overrides, platform should really not
|
||||
// be doing event handling. (need to fix Rift build in this regard).
|
||||
// g_core->platform->RunEvents();
|
||||
// }
|
||||
|
||||
// void AppAdapter::UpdatePauseResume_() {
|
||||
// if (app_paused_) {
|
||||
// // Unpause if no one wants pause.
|
||||
// if (!app_pause_requested_) {
|
||||
// OnAppResume_();
|
||||
// app_paused_ = false;
|
||||
// }
|
||||
// } else {
|
||||
// // OnAppPause if anyone wants.
|
||||
// if (app_pause_requested_) {
|
||||
// OnAppPause_();
|
||||
// app_paused_ = true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
void AppAdapter::OnAppPause_() {
|
||||
assert(g_core->InMainThread());
|
||||
|
||||
@ -188,7 +119,6 @@ void AppAdapter::OnAppPause_() {
|
||||
|
||||
void AppAdapter::OnAppResume_() {
|
||||
assert(g_core->InMainThread());
|
||||
// last_app_resume_time_ = g_core->GetAppTimeMillisecs();
|
||||
|
||||
// Spin all event-loops back up.
|
||||
EventLoop::SetEventLoopsPaused(false);
|
||||
@ -234,6 +164,7 @@ void AppAdapter::PauseApp() {
|
||||
"PauseApp@" + std::to_string(core::CorePlatform::GetCurrentMillisecs()));
|
||||
// assert(!app_pause_requested_);
|
||||
// app_pause_requested_ = true;
|
||||
app_paused_ = true;
|
||||
OnAppPause_();
|
||||
// UpdatePauseResume_();
|
||||
|
||||
@ -285,6 +216,7 @@ void AppAdapter::ResumeApp() {
|
||||
// assert(app_pause_requested_);
|
||||
// app_pause_requested_ = false;
|
||||
// UpdatePauseResume_();
|
||||
app_paused_ = false;
|
||||
OnAppResume_();
|
||||
if (g_buildconfig.debug_build()) {
|
||||
Log(LogLevel::kDebug,
|
||||
@ -309,4 +241,12 @@ auto AppAdapter::SupportsVSync() -> bool const { return false; }
|
||||
|
||||
auto AppAdapter::SupportsMaxFPS() -> bool const { return false; }
|
||||
|
||||
/// As a default, allow graphics stuff in the main thread.
|
||||
auto AppAdapter::InGraphicsContext() -> bool { return g_core->InMainThread(); }
|
||||
|
||||
/// As a default, assume our main thread *is* our graphics context.
|
||||
void AppAdapter::DoPushGraphicsContextRunnable(Runnable* runnable) {
|
||||
DoPushMainThreadRunnable(runnable);
|
||||
}
|
||||
|
||||
} // namespace ballistica::base
|
||||
|
||||
@ -52,6 +52,17 @@ class AppAdapter {
|
||||
DoPushMainThreadRunnable(NewLambdaRunnableUnmanaged(lambda));
|
||||
}
|
||||
|
||||
/// Should return whether the current thread and/or context setup is the
|
||||
/// one where graphics calls should be made. For the default
|
||||
/// implementation, this simply returns true in the main thread.
|
||||
virtual auto InGraphicsContext() -> bool;
|
||||
|
||||
/// Push a call to be run in the app's graphics context.
|
||||
template <typename F>
|
||||
void PushGraphicsContextCall(const F& lambda) {
|
||||
DoPushGraphicsContextRunnable(NewLambdaRunnableUnmanaged(lambda));
|
||||
}
|
||||
|
||||
/// Put the app into a paused state. Should be called from the main
|
||||
/// thread. Pauses work, closes network sockets, etc. May correspond to
|
||||
/// being backgrounded on mobile, being minimized on desktop, etc. It is
|
||||
@ -86,6 +97,10 @@ class AppAdapter {
|
||||
/// thread should call its RunAndLogErrors() method and then delete it.
|
||||
virtual void DoPushMainThreadRunnable(Runnable* runnable) = 0;
|
||||
|
||||
/// Push a raw pointer Runnable to be run in the platform's graphics
|
||||
/// context. By default this is simply the main thread.
|
||||
virtual void DoPushGraphicsContextRunnable(Runnable* runnable);
|
||||
|
||||
private:
|
||||
void OnAppPause_();
|
||||
void OnAppResume_();
|
||||
|
||||
@ -104,8 +104,6 @@ void AppAdapterSDL::DoApplyAppConfig() {
|
||||
void AppAdapterSDL::RunMainThreadEventLoopToCompletion() {
|
||||
assert(g_core->InMainThread());
|
||||
|
||||
// float smoothed_fps{};
|
||||
// float fps_smoothing{0.1f};
|
||||
while (!done_) {
|
||||
microsecs_t cycle_start_time = g_core->GetAppTimeMicrosecs();
|
||||
|
||||
@ -120,67 +118,69 @@ void AppAdapterSDL::RunMainThreadEventLoopToCompletion() {
|
||||
SDL_GL_SwapWindow(sdl_window_);
|
||||
}
|
||||
|
||||
// Sleep until we should start our next cycle (based on
|
||||
// max-frame-rate or other factors).
|
||||
|
||||
// Special case which means no max. Farewell poor laptop battery.
|
||||
if (max_fps_ == -1) {
|
||||
continue;
|
||||
}
|
||||
microsecs_t now = g_core->GetAppTimeMicrosecs();
|
||||
auto used_max_fps = max_fps_;
|
||||
millisecs_t millisecs_per_frame = 1000000 / used_max_fps;
|
||||
// Special case: if we've got vsync enabled, let's tweak max-fps to be
|
||||
// just a *tiny* bit higher than requested. This means if our max-fps
|
||||
// matches the refresh rate we'll be trying to render just a bit faster
|
||||
// than vsync which should push us up against the vsync wall and keep
|
||||
// vsync doing most of the delay work. In that case the logging below
|
||||
// should show mostly 'no sleep.'. Without this delay, our render
|
||||
// kick-offs tend to drift around the middle of the vsync cycle and I
|
||||
// worry there could be bad interference patterns in certain spots close
|
||||
// to the edges. Note that we want this tweak to be small enough that it
|
||||
// won't be noticable in situations where vsync and max-fps *don't*
|
||||
// match. (for instance limiting to 60hz on a 120hz vsynced monitor).
|
||||
if (vsync_actually_enabled_) {
|
||||
millisecs_per_frame = 99 * millisecs_per_frame / 100;
|
||||
}
|
||||
microsecs_t target_time =
|
||||
cycle_start_time + millisecs_per_frame - oversleep;
|
||||
|
||||
// Set a minimum so we don't sleep if we're within a few millisecs of
|
||||
// where we want to be. Sleep tends to run over by a bit so we'll
|
||||
// probably render closer to our target time by just skipping the sleep.
|
||||
// And the oversleep system will compensate just as it does if we sleep
|
||||
// too long.
|
||||
const microsecs_t min_sleep{2000};
|
||||
if (now + min_sleep >= target_time) {
|
||||
if (debug_log_sdl_frame_timing_) {
|
||||
Log(LogLevel::kDebug, "no sleep."); // 'till brooklyn!
|
||||
}
|
||||
} else {
|
||||
if (debug_log_sdl_frame_timing_) {
|
||||
char buf[256];
|
||||
snprintf(buf, sizeof(buf), "render %.1f sleep %.1f",
|
||||
(now - cycle_start_time) / 1000.0f,
|
||||
(target_time - now) / 1000.0f);
|
||||
Log(LogLevel::kDebug, buf);
|
||||
}
|
||||
g_core->platform->SleepMicrosecs(target_time - now);
|
||||
}
|
||||
|
||||
// Maintain an 'oversleep' amount to compensate for the timer not being
|
||||
// exact. This should keep us exactly at our target frame-rate in the
|
||||
// end.
|
||||
now = g_core->GetAppTimeMicrosecs();
|
||||
oversleep = now - target_time;
|
||||
|
||||
// Prevent oversleep from compensating by more than a few millisecs per
|
||||
// frame (not sure if this would ever be a problem but lets be safe).
|
||||
oversleep = std::max(int64_t{-3000}, oversleep);
|
||||
oversleep = std::min(int64_t{3000}, oversleep);
|
||||
// In some cases, sleep until we should start our next cycle (depending
|
||||
// on max-frame-rate or other factors).
|
||||
SleepUntilNextEventCycle_(cycle_start_time);
|
||||
}
|
||||
}
|
||||
|
||||
void AppAdapterSDL::SleepUntilNextEventCycle_(microsecs_t cycle_start_time) {
|
||||
// Special case which means no max. Farewell poor laptop battery.
|
||||
if (max_fps_ == -1) {
|
||||
return;
|
||||
}
|
||||
microsecs_t now = g_core->GetAppTimeMicrosecs();
|
||||
auto used_max_fps = max_fps_;
|
||||
millisecs_t millisecs_per_frame = 1000000 / used_max_fps;
|
||||
// Special case: if we've got vsync enabled, let's tweak max-fps to be
|
||||
// just a *tiny* bit higher than requested. This means if our max-fps
|
||||
// matches the refresh rate we'll be trying to render just a bit faster
|
||||
// than vsync which should push us up against the vsync wall and keep
|
||||
// vsync doing most of the delay work. In that case the logging below
|
||||
// should show mostly 'no sleep.'. Without this delay, our render
|
||||
// kick-offs tend to drift around the middle of the vsync cycle and I
|
||||
// worry there could be bad interference patterns in certain spots close
|
||||
// to the edges. Note that we want this tweak to be small enough that it
|
||||
// won't be noticable in situations where vsync and max-fps *don't*
|
||||
// match. (for instance limiting to 60hz on a 120hz vsynced monitor).
|
||||
if (vsync_actually_enabled_) {
|
||||
millisecs_per_frame = 99 * millisecs_per_frame / 100;
|
||||
}
|
||||
microsecs_t target_time = cycle_start_time + millisecs_per_frame - oversleep_;
|
||||
|
||||
// Set a minimum so we don't sleep if we're within a few millisecs of
|
||||
// where we want to be. Sleep tends to run over by a bit so we'll
|
||||
// probably render closer to our target time by just skipping the sleep.
|
||||
// And the oversleep system will compensate just as it does if we sleep
|
||||
// too long.
|
||||
const microsecs_t min_sleep{2000};
|
||||
if (now + min_sleep >= target_time) {
|
||||
if (debug_log_sdl_frame_timing_) {
|
||||
Log(LogLevel::kDebug, "no sleep."); // 'till brooklyn!
|
||||
}
|
||||
} else {
|
||||
if (debug_log_sdl_frame_timing_) {
|
||||
char buf[256];
|
||||
snprintf(buf, sizeof(buf), "render %.1f sleep %.1f",
|
||||
(now - cycle_start_time) / 1000.0f,
|
||||
(target_time - now) / 1000.0f);
|
||||
Log(LogLevel::kDebug, buf);
|
||||
}
|
||||
g_core->platform->SleepMicrosecs(target_time - now);
|
||||
}
|
||||
|
||||
// Maintain an 'oversleep' amount to compensate for the timer not being
|
||||
// exact. This should keep us exactly at our target frame-rate in the
|
||||
// end.
|
||||
now = g_core->GetAppTimeMicrosecs();
|
||||
oversleep_ = now - target_time;
|
||||
|
||||
// Prevent oversleep from compensating by more than a few millisecs per
|
||||
// frame (not sure if this would ever be a problem but lets be safe).
|
||||
oversleep_ = std::max(int64_t{-3000}, oversleep_);
|
||||
oversleep_ = std::min(int64_t{3000}, oversleep_);
|
||||
}
|
||||
|
||||
void AppAdapterSDL::DoPushMainThreadRunnable(Runnable* runnable) {
|
||||
assert(sdl_runnable_event_id_ != 0);
|
||||
SDL_Event event;
|
||||
@ -454,7 +454,7 @@ void AppAdapterSDL::SetScreen_(
|
||||
bool fullscreen, int max_fps, VSyncRequest vsync_requested,
|
||||
TextureQualityRequest texture_quality_requested,
|
||||
GraphicsQualityRequest graphics_quality_requested) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(InGraphicsContext());
|
||||
assert(!g_core->HeadlessMode());
|
||||
|
||||
// If we know what we support, filter our request types to what is
|
||||
@ -554,7 +554,7 @@ void AppAdapterSDL::SetScreen_(
|
||||
void AppAdapterSDL::ReloadRenderer_(
|
||||
bool fullscreen, GraphicsQualityRequest graphics_quality_requested,
|
||||
TextureQualityRequest texture_quality_requested) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
|
||||
auto* gs = g_base->graphics_server;
|
||||
|
||||
@ -635,7 +635,7 @@ void AppAdapterSDL::ReloadRenderer_(
|
||||
}
|
||||
|
||||
void AppAdapterSDL::UpdateScreenSizes_() {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
|
||||
// Grab logical window dimensions (points?).
|
||||
// This is the coordinate space SDL's events deal in.
|
||||
|
||||
@ -61,6 +61,7 @@ class AppAdapterSDL : public AppAdapter {
|
||||
// void UpdateAutoVSync_(int diff);
|
||||
void AddSDLInputDevice_(JoystickInput* input, int index);
|
||||
void RemoveSDLInputDevice_(int index);
|
||||
void SleepUntilNextEventCycle_(microsecs_t cycle_start_time);
|
||||
// millisecs_t last_swap_time_{};
|
||||
// millisecs_t swap_start_time_{};
|
||||
// int too_slow_frame_count_{};
|
||||
@ -80,7 +81,7 @@ class AppAdapterSDL : public AppAdapter {
|
||||
bool fullscreen_{};
|
||||
VSync vsync_{VSync::kUnset};
|
||||
bool vsync_actually_enabled_{};
|
||||
microsecs_t oversleep{};
|
||||
microsecs_t oversleep_{};
|
||||
int max_fps_{60};
|
||||
bool debug_log_sdl_frame_timing_{};
|
||||
// std::unique_ptr<GLContext> gl_context_;
|
||||
|
||||
@ -17,7 +17,7 @@ auto AppAdapterVR::ManagesMainThreadEventLoop() const -> bool { return false; }
|
||||
|
||||
void AppAdapterVR::PushVRSimpleRemoteStateCall(
|
||||
const VRSimpleRemoteState& state) {
|
||||
g_base->app_adapter->PushMainThreadCall([this, state] {
|
||||
g_base->app_adapter->PushGraphicsContextCall([this, state] {
|
||||
// Convert this to a full hands state, adding in some simple elbow
|
||||
// positioning of our own and left/right.
|
||||
VRHandsState s;
|
||||
@ -48,7 +48,7 @@ void AppAdapterVR::VRPreDraw() {
|
||||
|| !g_base->graphics_server->renderer()) {
|
||||
return;
|
||||
}
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
// FIXME - this is internal graphics-server details that the render-server
|
||||
// should handle.
|
||||
Log(LogLevel::kWarning, "FIXME: Have GraphicsServer handle VR drawing.");
|
||||
@ -65,7 +65,7 @@ void AppAdapterVR::VRPreDraw() {
|
||||
}
|
||||
|
||||
void AppAdapterVR::VRPostDraw() {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
if (!g_base || !g_base->graphics_server
|
||||
|| !g_base->graphics_server->renderer()) {
|
||||
return;
|
||||
@ -80,14 +80,14 @@ void AppAdapterVR::VRPostDraw() {
|
||||
|
||||
void AppAdapterVR::VRSetHead(float tx, float ty, float tz, float yaw,
|
||||
float pitch, float roll) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
Renderer* renderer = g_base->graphics_server->renderer();
|
||||
if (renderer == nullptr) return;
|
||||
renderer->VRSetHead(tx, ty, tz, yaw, pitch, roll);
|
||||
}
|
||||
|
||||
void AppAdapterVR::VRSetHands(const VRHandsState& state) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
|
||||
// Pass this along to the renderer (in this same thread) for drawing (so
|
||||
// hands can be drawn at their absolute most up-to-date positions, etc).
|
||||
@ -114,7 +114,7 @@ void AppAdapterVR::VRDrawEye(int eye, float yaw, float pitch, float roll,
|
||||
|| !g_base->graphics_server->renderer()) {
|
||||
return;
|
||||
}
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
if (vr_render_frame_def_) {
|
||||
// Set up VR eye stuff.
|
||||
Renderer* renderer = g_base->graphics_server->renderer();
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
|
||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||
#include "ballistica/base/app_mode/app_mode.h"
|
||||
#include "ballistica/base/assets/assets_server.h"
|
||||
#include "ballistica/base/assets/collision_mesh_asset.h"
|
||||
@ -409,7 +410,7 @@ void Assets::MarkAllAssetsForLoad() {
|
||||
// Call this from the graphics thread to immediately unload all
|
||||
// assets used by it. (for when GL context gets lost, etc).
|
||||
void Assets::UnloadRendererBits(bool do_textures, bool do_meshes) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
// need to keep lists locked while iterating over them..
|
||||
AssetListLock m_lock;
|
||||
if (do_textures) {
|
||||
@ -728,7 +729,7 @@ auto Assets::RunPendingAudioLoads() -> bool {
|
||||
|
||||
// Runs the pending loads that need to run from the graphics thread.
|
||||
auto Assets::RunPendingGraphicsLoads() -> bool {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
return RunPendingLoadList(&pending_loads_graphics_);
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "ballistica/base/assets/texture_asset.h"
|
||||
|
||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||
#include "ballistica/base/assets/texture_asset_preload_data.h"
|
||||
#include "ballistica/base/assets/texture_asset_renderer_data.h"
|
||||
#include "ballistica/base/graphics/graphics.h"
|
||||
@ -425,7 +426,7 @@ void TextureAsset::DoPreload() {
|
||||
}
|
||||
|
||||
void TextureAsset::DoLoad() {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
assert(!renderer_data_.Exists());
|
||||
renderer_data_ = g_base->graphics_server->renderer()->NewTextureData(*this);
|
||||
assert(renderer_data_.Exists());
|
||||
@ -441,7 +442,7 @@ void TextureAsset::DoLoad() {
|
||||
}
|
||||
|
||||
void TextureAsset::DoUnload() {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
assert(valid_);
|
||||
assert(renderer_data_.Exists());
|
||||
renderer_data_.Clear();
|
||||
|
||||
@ -199,8 +199,7 @@ void AudioServer::OnAppStartInThread() {
|
||||
}
|
||||
#endif // BA_RIFT_BUILD
|
||||
|
||||
ALCdevice* device;
|
||||
device = alcOpenDevice(al_device_name);
|
||||
auto* device = alcOpenDevice(al_device_name);
|
||||
if (!device) {
|
||||
FatalError(
|
||||
"No audio devices found. Do you have speakers/headphones/etc. "
|
||||
|
||||
@ -468,15 +468,6 @@ auto BaseFeatureSet::InLogicThread() const -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto BaseFeatureSet::InGraphicsThread() const -> bool {
|
||||
// FIXME.
|
||||
return g_core->InMainThread();
|
||||
// if (auto* loop = graphics_server->event_loop()) {
|
||||
// return loop->ThreadIsCurrent();
|
||||
// }
|
||||
// return false;
|
||||
}
|
||||
|
||||
auto BaseFeatureSet::InAudioThread() const -> bool {
|
||||
if (auto* loop = audio_server->event_loop()) {
|
||||
return loop->ThreadIsCurrent();
|
||||
|
||||
@ -682,7 +682,6 @@ class BaseFeatureSet : public FeatureSetNativeComponent,
|
||||
|
||||
auto InAssetsThread() const -> bool override;
|
||||
auto InLogicThread() const -> bool override;
|
||||
auto InGraphicsThread() const -> bool override;
|
||||
auto InAudioThread() const -> bool override;
|
||||
auto InBGDynamicsThread() const -> bool override;
|
||||
auto InNetworkWriteThread() const -> bool override;
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
|
||||
#if BA_ENABLE_OPENGL
|
||||
|
||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||
#include "ballistica/base/graphics/gl/renderer_gl.h"
|
||||
#include "ballistica/base/graphics/graphics_server.h"
|
||||
|
||||
@ -46,7 +47,7 @@ class RendererGL::FramebufferObjectGL : public Framebuffer {
|
||||
|
||||
void Load(bool force_low_quality = false) {
|
||||
if (loaded_) return;
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
BA_DEBUG_CHECK_GL_ERROR;
|
||||
GLenum status;
|
||||
BA_DEBUG_CHECK_GL_ERROR;
|
||||
@ -246,7 +247,7 @@ class RendererGL::FramebufferObjectGL : public Framebuffer {
|
||||
}
|
||||
|
||||
void Unload() {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
if (!loaded_) return;
|
||||
|
||||
// If our textures are currently bound as anything, clear that out.
|
||||
@ -288,7 +289,7 @@ class RendererGL::FramebufferObjectGL : public Framebuffer {
|
||||
}
|
||||
|
||||
void Bind() {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
renderer_->BindFramebuffer(framebuffer_);
|
||||
// if (time(nullptr)%2 == 0) {
|
||||
// glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
|
||||
#if BA_ENABLE_OPENGL
|
||||
|
||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||
#include "ballistica/base/graphics/gl/gl_sys.h"
|
||||
#include "ballistica/base/graphics/gl/renderer_gl.h"
|
||||
#include "ballistica/base/graphics/graphics_server.h"
|
||||
@ -23,7 +24,7 @@ class RendererGL::MeshAssetDataGL : public MeshAssetRendererData {
|
||||
name_ = model.GetName();
|
||||
#endif
|
||||
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
BA_DEBUG_CHECK_GL_ERROR;
|
||||
|
||||
// Create our vertex array to hold all this state.
|
||||
@ -98,7 +99,7 @@ class RendererGL::MeshAssetDataGL : public MeshAssetRendererData {
|
||||
}
|
||||
|
||||
~MeshAssetDataGL() override {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
BA_DEBUG_CHECK_GL_ERROR;
|
||||
|
||||
// Unbind if we're bound; otherwise if a new vao pops up with our same
|
||||
|
||||
@ -27,7 +27,7 @@ class RendererGL::MeshDataGL : public MeshRendererData {
|
||||
: renderer_(renderer),
|
||||
uses_secondary_data_(static_cast<bool>(flags & kUsesSecondaryBuffer)),
|
||||
uses_index_data_(static_cast<bool>(flags & kUsesIndexBuffer)) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
BA_DEBUG_CHECK_GL_ERROR;
|
||||
|
||||
// Create our vertex array to hold all this state.
|
||||
@ -85,7 +85,7 @@ class RendererGL::MeshDataGL : public MeshRendererData {
|
||||
}
|
||||
|
||||
~MeshDataGL() override {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
// Unbind if we're bound; otherwise we might prevent a new vao that
|
||||
// reuses our ID from binding.
|
||||
if (vao_ == renderer_->current_vertex_array_) {
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
|
||||
#if BA_ENABLE_OPENGL
|
||||
|
||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||
#include "ballistica/base/graphics/gl/renderer_gl.h"
|
||||
#include "ballistica/base/graphics/graphics_server.h"
|
||||
|
||||
@ -18,7 +19,7 @@ class RendererGL::ShaderGL : public Object {
|
||||
}
|
||||
|
||||
ShaderGL(GLenum type_in, const std::string& src_in) : type_(type_in) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
BA_DEBUG_CHECK_GL_ERROR;
|
||||
assert(type_ == GL_FRAGMENT_SHADER || type_ == GL_VERTEX_SHADER);
|
||||
shader_ = glCreateShader(type_);
|
||||
@ -73,7 +74,7 @@ class RendererGL::ShaderGL : public Object {
|
||||
}
|
||||
|
||||
~ShaderGL() override {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
if (!g_base->graphics_server->renderer_context_lost()) {
|
||||
glDeleteShader(shader_);
|
||||
BA_DEBUG_CHECK_GL_ERROR;
|
||||
@ -127,7 +128,7 @@ class RendererGL::ProgramGL {
|
||||
renderer_(renderer),
|
||||
pflags_(pflags),
|
||||
name_(std::move(name)) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
BA_DEBUG_CHECK_GL_ERROR;
|
||||
program_ = glCreateProgram();
|
||||
BA_PRECONDITION(program_);
|
||||
@ -209,7 +210,7 @@ class RendererGL::ProgramGL {
|
||||
}
|
||||
|
||||
virtual ~ProgramGL() {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
if (!g_base->graphics_server->renderer_context_lost()) {
|
||||
glDetachShader(program_, fragment_shader_->shader());
|
||||
glDetachShader(program_, vertex_shader_->shader());
|
||||
|
||||
@ -23,7 +23,7 @@ class RendererGL::RenderTargetGL : public RenderTarget {
|
||||
|
||||
void DrawBegin(bool must_clear_color, float clear_r, float clear_g,
|
||||
float clear_b, float clear_a) override {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
BA_DEBUG_CHECK_GL_ERROR;
|
||||
|
||||
Bind();
|
||||
@ -94,7 +94,7 @@ class RendererGL::RenderTargetGL : public RenderTarget {
|
||||
// Screen constructor.
|
||||
explicit RenderTargetGL(RendererGL* renderer)
|
||||
: RenderTarget(Type::kScreen), renderer_(renderer) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
depth_ = true;
|
||||
|
||||
// This will update our width/height values.
|
||||
@ -106,7 +106,7 @@ class RendererGL::RenderTargetGL : public RenderTarget {
|
||||
bool linear_interp, bool depth, bool texture,
|
||||
bool depth_texture, bool high_quality, bool msaa, bool alpha)
|
||||
: RenderTarget(Type::kFramebuffer), renderer_(renderer) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
BA_DEBUG_CHECK_GL_ERROR;
|
||||
framebuffer_ = Object::New<FramebufferObjectGL>(
|
||||
renderer, width, height, linear_interp, depth, texture, depth_texture,
|
||||
|
||||
@ -87,7 +87,7 @@ bool RendererGL::is_extra_speedy_android_device_{};
|
||||
#endif
|
||||
|
||||
RendererGL::RendererGL() {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
|
||||
if (explicit_bool(BA_FORCE_CHECK_GL_ERRORS)) {
|
||||
ScreenMessage("GL ERROR CHECKS ENABLED");
|
||||
@ -175,7 +175,7 @@ static auto CheckGLExtension(const std::vector<std::string>& exts,
|
||||
|
||||
void RendererGL::CheckGLCapabilities_() {
|
||||
BA_DEBUG_CHECK_GL_ERROR;
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
|
||||
draws_shields_funny_set_ = true;
|
||||
|
||||
@ -653,7 +653,7 @@ auto RendererGL::DebugGLGetInt(GLenum name) -> int {
|
||||
// This is probably inefficient so make sure we don't leave it on in
|
||||
// release builds.
|
||||
assert(g_buildconfig.debug_build());
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
|
||||
// Clear any error coming in; don't want to die for something that's not
|
||||
// ours.
|
||||
@ -874,7 +874,7 @@ void RendererGL::InvalidateFramebuffer(bool color, bool depth,
|
||||
}
|
||||
|
||||
RendererGL::~RendererGL() {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
printf("FIXME: need to unload renderer on destroy.\n");
|
||||
// Unload();
|
||||
BA_DEBUG_CHECK_GL_ERROR;
|
||||
@ -2610,7 +2610,7 @@ auto RendererGL::GetFunkyDepthIssue_() -> bool {
|
||||
|
||||
#if BA_OSTYPE_ANDROID
|
||||
std::string RendererGL::GetAutoAndroidRes() {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
|
||||
const char* renderer = (const char*)glGetString(GL_RENDERER);
|
||||
|
||||
@ -2636,7 +2636,7 @@ std::string RendererGL::GetAutoAndroidRes() {
|
||||
#endif // BA_OSTYPE_ANDROID
|
||||
|
||||
auto RendererGL::GetAutoTextureQuality() -> TextureQuality {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
|
||||
TextureQuality qual{TextureQuality::kHigh};
|
||||
|
||||
@ -2668,7 +2668,7 @@ auto RendererGL::GetAutoTextureQuality() -> TextureQuality {
|
||||
}
|
||||
|
||||
auto RendererGL::GetAutoGraphicsQuality() -> GraphicsQuality {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
GraphicsQuality q{GraphicsQuality::kMedium};
|
||||
#if BA_OSTYPE_ANDROID
|
||||
// lets be cheaper in VR mode since we draw twice..
|
||||
@ -2691,7 +2691,7 @@ auto RendererGL::GetAutoGraphicsQuality() -> GraphicsQuality {
|
||||
void RendererGL::RetainShader_(ProgramGL* p) { shaders_.emplace_back(p); }
|
||||
|
||||
void RendererGL::Load() {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
assert(!data_loaded_);
|
||||
assert(g_base->graphics_server->graphics_quality_set());
|
||||
BA_DEBUG_CHECK_GL_ERROR;
|
||||
@ -2920,7 +2920,7 @@ void RendererGL::PostLoad() {
|
||||
}
|
||||
|
||||
void RendererGL::Unload() {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
BA_DEBUG_CHECK_GL_ERROR;
|
||||
assert(data_loaded_);
|
||||
Renderer::Unload();
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
|
||||
#if BA_ENABLE_OPENGL
|
||||
|
||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||
#include "ballistica/base/assets/texture_asset_preload_data.h"
|
||||
#include "ballistica/base/assets/texture_asset_renderer_data.h"
|
||||
#include "ballistica/base/graphics/gl/renderer_gl.h"
|
||||
@ -16,14 +17,14 @@ class RendererGL::TextureDataGL : public TextureAssetRendererData {
|
||||
public:
|
||||
TextureDataGL(const TextureAsset& texture_in, RendererGL* renderer_in)
|
||||
: tex_media_(&texture_in), texture_(0), renderer_(renderer_in) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
BA_DEBUG_CHECK_GL_ERROR;
|
||||
glGenTextures(1, &texture_);
|
||||
BA_DEBUG_CHECK_GL_ERROR;
|
||||
}
|
||||
|
||||
~TextureDataGL() override {
|
||||
if (!g_base->InGraphicsThread()) {
|
||||
if (!g_base->app_adapter->InGraphicsContext()) {
|
||||
Log(LogLevel::kError, "TextureDataGL dying outside of graphics thread.");
|
||||
} else {
|
||||
// If we're currently bound as anything, clear that out (otherwise a
|
||||
@ -46,7 +47,7 @@ class RendererGL::TextureDataGL : public TextureAssetRendererData {
|
||||
auto GetTexture() const -> GLuint { return texture_; }
|
||||
|
||||
void Load() override {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
BA_DEBUG_CHECK_GL_ERROR;
|
||||
|
||||
if (tex_media_->texture_type() == TextureType::k2D) {
|
||||
|
||||
@ -1121,14 +1121,24 @@ void Graphics::BuildAndPushFrameDef() {
|
||||
|
||||
// Store how much time this frame_def represents.
|
||||
auto display_time_microsecs = g_base->logic->display_time_microsecs();
|
||||
auto display_time_millisecs = display_time_microsecs / 1000;
|
||||
|
||||
// Clamp a frame-def's elapsed time to 1/10th of a second even if it has
|
||||
// been longer than that since the last. Don't want things like
|
||||
// motion-blur to get out of control.
|
||||
millisecs_t elapsed_microsecs =
|
||||
microsecs_t elapsed_microsecs =
|
||||
std::min(microsecs_t{100000},
|
||||
display_time_microsecs - last_create_frame_def_time_);
|
||||
last_create_frame_def_time_ = display_time_microsecs;
|
||||
display_time_microsecs - last_create_frame_def_time_microsecs_);
|
||||
last_create_frame_def_time_microsecs_ = display_time_microsecs;
|
||||
|
||||
// We need to do a separate elapsed calculation for milliseconds. It would
|
||||
// seem that we could just calc this based on our elapsed microseconds,
|
||||
// but the problem is that at very high frame rates we wind up always
|
||||
// rounding down to 0.
|
||||
millisecs_t elapsed_millisecs =
|
||||
std::min(millisecs_t{100},
|
||||
display_time_millisecs - last_create_frame_def_time_millisecs_);
|
||||
last_create_frame_def_time_millisecs_ = display_time_millisecs;
|
||||
|
||||
frame_def_count_++;
|
||||
|
||||
@ -1153,6 +1163,7 @@ void Graphics::BuildAndPushFrameDef() {
|
||||
frame_def->set_display_time_microsecs(
|
||||
g_base->logic->display_time_microsecs());
|
||||
frame_def->set_display_time_elapsed_microsecs(elapsed_microsecs);
|
||||
frame_def->set_display_time_elapsed_millisecs(elapsed_millisecs);
|
||||
frame_def->set_frame_number(frame_def_count_);
|
||||
frame_def->set_frame_number_filtered(frame_def_count_filtered_);
|
||||
|
||||
|
||||
@ -375,7 +375,8 @@ class Graphics {
|
||||
std::list<Object::Ref<PythonContextCall>> clean_frame_commands_;
|
||||
std::vector<MeshData*> mesh_data_creates_;
|
||||
std::vector<MeshData*> mesh_data_destroys_;
|
||||
millisecs_t last_create_frame_def_time_{};
|
||||
microsecs_t last_create_frame_def_time_microsecs_{};
|
||||
millisecs_t last_create_frame_def_time_millisecs_{};
|
||||
Vector3f shadow_offset_{0.0f, 0.0f, 0.0f};
|
||||
Vector2f shadow_scale_{1.0f, 1.0f};
|
||||
Vector3f tint_{1.0f, 1.0f, 1.0f};
|
||||
|
||||
@ -22,11 +22,11 @@
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
GraphicsServer::GraphicsServer() {}
|
||||
GraphicsServer::GraphicsServer() = default;
|
||||
GraphicsServer::~GraphicsServer() = default;
|
||||
|
||||
void GraphicsServer::SetRenderHold() {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
render_hold_++;
|
||||
}
|
||||
|
||||
@ -46,7 +46,7 @@ void GraphicsServer::EnqueueFrameDef(FrameDef* framedef) {
|
||||
}
|
||||
|
||||
auto GraphicsServer::TryRender() -> bool {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
|
||||
bool success{};
|
||||
|
||||
@ -75,7 +75,7 @@ auto GraphicsServer::TryRender() -> bool {
|
||||
}
|
||||
|
||||
auto GraphicsServer::WaitForRenderFrameDef_() -> FrameDef* {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
millisecs_t app_time = g_core->GetAppTimeMillisecs();
|
||||
|
||||
if (!renderer_) {
|
||||
@ -127,13 +127,13 @@ auto GraphicsServer::WaitForRenderFrameDef_() -> FrameDef* {
|
||||
}
|
||||
|
||||
void GraphicsServer::ApplyFrameDefSettings(FrameDef* frame_def) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
tv_border_ = frame_def->tv_border();
|
||||
}
|
||||
|
||||
// Runs any mesh updates contained in the frame-def.
|
||||
void GraphicsServer::RunFrameDefMeshUpdates(FrameDef* frame_def) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
|
||||
// Run any mesh-data creates/destroys included with this frame_def.
|
||||
for (auto&& i : frame_def->mesh_data_creates()) {
|
||||
@ -151,7 +151,7 @@ void GraphicsServer::RunFrameDefMeshUpdates(FrameDef* frame_def) {
|
||||
|
||||
// Renders shadow passes and other common parts of a frame_def.
|
||||
void GraphicsServer::PreprocessRenderFrameDef(FrameDef* frame_def) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
|
||||
// Now let the renderer do any preprocess passes (shadows, etc).
|
||||
assert(renderer_);
|
||||
@ -179,7 +179,7 @@ void GraphicsServer::FinishRenderFrameDef(FrameDef* frame_def) {
|
||||
|
||||
// Reload all media (for debugging/benchmarking purposes).
|
||||
void GraphicsServer::ReloadMedia_() {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
|
||||
// Immediately unload all renderer data here in this thread.
|
||||
if (renderer_) {
|
||||
@ -205,7 +205,7 @@ void GraphicsServer::ReloadMedia_() {
|
||||
|
||||
// Call when a renderer context has been lost.
|
||||
void GraphicsServer::ReloadLostRenderer() {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
|
||||
if (!renderer_) {
|
||||
Log(LogLevel::kError, "No renderer on GraphicsServer::ReloadLostRenderer.");
|
||||
@ -274,14 +274,14 @@ void GraphicsServer::SetNullGraphics() {
|
||||
}
|
||||
|
||||
void GraphicsServer::set_renderer(Renderer* renderer) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
assert(!renderer_loaded_);
|
||||
assert(!renderer_);
|
||||
renderer_ = renderer;
|
||||
}
|
||||
|
||||
void GraphicsServer::LoadRenderer() {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
if (!renderer_) {
|
||||
Log(LogLevel::kError, "LoadRenderer() called with no renderer present.");
|
||||
return;
|
||||
@ -358,15 +358,14 @@ void GraphicsServer::LoadRenderer() {
|
||||
|
||||
renderer_loaded_ = true;
|
||||
|
||||
// Set a render-hold so we ignore all frame_defs up until the point at
|
||||
// which we receive the corresponding remove-hold. (At which point
|
||||
// subsequent frame-defs will be be progress-bar frame_defs so we won't
|
||||
// hitch if we actually render them.)
|
||||
// Set an immediate render-hold so we ignore all frame_defs up until the
|
||||
// point at which we receive the corresponding remove-hold. (At which
|
||||
// point subsequent frame-defs will be be progress-bar frame_defs so we
|
||||
// won't hitch if we actually render them.)
|
||||
SetRenderHold();
|
||||
|
||||
// Now tell the logic thread to kick off loads for everything, flip on
|
||||
// progress bar drawing, and then tell the graphics thread to stop
|
||||
// ignoring frame-defs.
|
||||
// progress bar drawing, and then ship a remove-hold call back to us.
|
||||
g_base->logic->event_loop()->PushCall([this] {
|
||||
g_base->assets->MarkAllAssetsForLoad();
|
||||
g_base->graphics->set_internal_components_inited(false);
|
||||
@ -376,7 +375,7 @@ void GraphicsServer::LoadRenderer() {
|
||||
}
|
||||
|
||||
void GraphicsServer::UnloadRenderer() {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
if (!renderer_) {
|
||||
Log(LogLevel::kError, "UnloadRenderer() called with no renderer present.");
|
||||
return;
|
||||
@ -417,7 +416,7 @@ void GraphicsServer::CalcVirtualRes_(float* x, float* y) {
|
||||
}
|
||||
|
||||
void GraphicsServer::UpdateVirtualScreenRes_() {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
|
||||
// In vr mode our virtual res is independent of our screen size.
|
||||
// (since it gets drawn to an overlay)
|
||||
@ -432,7 +431,7 @@ void GraphicsServer::UpdateVirtualScreenRes_() {
|
||||
}
|
||||
|
||||
void GraphicsServer::SetScreenResolution(float h, float v) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
|
||||
// Ignore redundant sets.
|
||||
if (res_x_ == h && res_y_ == v) {
|
||||
@ -477,50 +476,9 @@ void GraphicsServer::HandlePushAndroidRes(const std::string& android_res) {
|
||||
}
|
||||
}
|
||||
|
||||
// void GraphicsServer::HandleFullscreenToggling(bool do_set_existing_fs,
|
||||
// bool do_toggle_fs,
|
||||
// bool fullscreen) {
|
||||
// if (do_set_existing_fs) {
|
||||
// #if BA_SDL2_BUILD
|
||||
// bool rift_vr_mode = false;
|
||||
// #if BA_RIFT_BUILD
|
||||
// if (g_core->IsVRMode()) {
|
||||
// rift_vr_mode = true;
|
||||
// }
|
||||
// #endif // BA_RIFT_BUILD
|
||||
// if (explicit_bool(!rift_vr_mode)) {
|
||||
// #if BA_OSTYPE_IOS_TVOS
|
||||
// set_fullscreen_enabled(true);
|
||||
|
||||
// #else // BA_OSTYPE_IOS_TVOS
|
||||
// auto* app_adapter_sdl = AppAdapterSDL::Get();
|
||||
// uint32_t fullscreen_flag = SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
// SDL_SetWindowFullscreen(app_adapter_sdl->sdl_window_,
|
||||
// fullscreen ? fullscreen_flag : 0);
|
||||
|
||||
// // Ideally this should be driven by OS events and not just explicitly
|
||||
// by
|
||||
// // us (so, for instance, if someone presses fullscreen on mac we'd know
|
||||
// // we've gone into fullscreen). But this works for now.
|
||||
// set_fullscreen_enabled(fullscreen);
|
||||
// #endif // BA_OSTYPE_IOS_TVOS
|
||||
// }
|
||||
// #endif // BA_SDL2_BUILD
|
||||
// } else if (do_toggle_fs) {
|
||||
// // If we're doing a fullscreen-toggle, we need to do it after coming out
|
||||
// of
|
||||
// // sync mode (because the toggle triggers sync-mode itself).
|
||||
// #if BA_OSTYPE_MACOS && BA_XCODE_BUILD && !BA_XCODE_NEW_PROJECT
|
||||
// #if BA_ENABLE_OPENGL
|
||||
// SDL_WM_ToggleFullScreen(gl_context_->sdl_screen_surface());
|
||||
// #endif
|
||||
// #endif // macos && xcode_build
|
||||
// }
|
||||
// }
|
||||
|
||||
void GraphicsServer::SetTextureCompressionTypes(
|
||||
const std::list<TextureCompressionType>& types) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
texture_compression_types_ = 0;
|
||||
for (auto&& i : types) {
|
||||
texture_compression_types_ |= (0x01u << (static_cast<uint32_t>(i)));
|
||||
@ -531,7 +489,7 @@ void GraphicsServer::SetTextureCompressionTypes(
|
||||
void GraphicsServer::SetOrthoProjection(float left, float right, float bottom,
|
||||
float top, float nearval,
|
||||
float farval) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
float tx = -((right + left) / (right - left));
|
||||
float ty = -((top + bottom) / (top - bottom));
|
||||
float tz = -((farval + nearval) / (farval - nearval));
|
||||
@ -562,7 +520,7 @@ void GraphicsServer::SetOrthoProjection(float left, float right, float bottom,
|
||||
|
||||
void GraphicsServer::SetCamera(const Vector3f& eye, const Vector3f& target,
|
||||
const Vector3f& up_vector) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
|
||||
// Reset the modelview stack.
|
||||
model_view_stack_.clear();
|
||||
@ -604,7 +562,7 @@ void GraphicsServer::SetCamera(const Vector3f& eye, const Vector3f& target,
|
||||
}
|
||||
|
||||
void GraphicsServer::UpdateCamOrientMatrix_() {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
if (cam_orient_matrix_dirty_) {
|
||||
cam_orient_matrix_ = kMatrix44fIdentity;
|
||||
Vector3f to_cam = cam_pos_ - cam_target_;
|
||||
@ -631,12 +589,12 @@ void GraphicsServer::UpdateCamOrientMatrix_() {
|
||||
}
|
||||
|
||||
void GraphicsServer::PushReloadMediaCall() {
|
||||
g_base->app_adapter->PushMainThreadCall([this] { ReloadMedia_(); });
|
||||
g_base->app_adapter->PushGraphicsContextCall([this] { ReloadMedia_(); });
|
||||
}
|
||||
|
||||
void GraphicsServer::PushSetScreenPixelScaleCall(float pixel_scale) {
|
||||
g_base->app_adapter->PushMainThreadCall([this, pixel_scale] {
|
||||
assert(g_base->InGraphicsThread());
|
||||
g_base->app_adapter->PushGraphicsContextCall([this, pixel_scale] {
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
if (!renderer_) {
|
||||
return;
|
||||
}
|
||||
@ -646,8 +604,8 @@ void GraphicsServer::PushSetScreenPixelScaleCall(float pixel_scale) {
|
||||
|
||||
void GraphicsServer::PushComponentUnloadCall(
|
||||
const std::vector<Object::Ref<Asset>*>& components) {
|
||||
g_base->app_adapter->PushMainThreadCall([components] {
|
||||
assert(g_base->InGraphicsThread());
|
||||
g_base->app_adapter->PushGraphicsContextCall([components] {
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
// Unload the components.
|
||||
for (auto&& i : components) {
|
||||
(**i).Unload();
|
||||
@ -662,8 +620,8 @@ void GraphicsServer::PushComponentUnloadCall(
|
||||
}
|
||||
|
||||
void GraphicsServer::PushRemoveRenderHoldCall() {
|
||||
g_base->app_adapter->PushMainThreadCall([this] {
|
||||
assert(g_base->InGraphicsThread());
|
||||
g_base->app_adapter->PushGraphicsContextCall([this] {
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
assert(render_hold_);
|
||||
render_hold_--;
|
||||
if (render_hold_ < 0) {
|
||||
@ -673,4 +631,8 @@ void GraphicsServer::PushRemoveRenderHoldCall() {
|
||||
});
|
||||
}
|
||||
|
||||
auto GraphicsServer::InGraphicsContext_() const -> bool {
|
||||
return g_base->app_adapter->InGraphicsContext();
|
||||
}
|
||||
|
||||
} // namespace ballistica::base
|
||||
|
||||
@ -226,27 +226,27 @@ class GraphicsServer {
|
||||
}
|
||||
|
||||
auto screen_pixel_width() const -> float {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(InGraphicsContext_());
|
||||
return res_x_;
|
||||
}
|
||||
|
||||
auto screen_pixel_height() const -> float {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(InGraphicsContext_());
|
||||
return res_y_;
|
||||
}
|
||||
|
||||
auto screen_virtual_width() const -> float {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(InGraphicsContext_());
|
||||
return res_x_virtual_;
|
||||
}
|
||||
|
||||
auto screen_virtual_height() const -> float {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(InGraphicsContext_());
|
||||
return res_y_virtual_;
|
||||
}
|
||||
|
||||
auto tv_border() const {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(InGraphicsContext_());
|
||||
return tv_border_;
|
||||
}
|
||||
|
||||
@ -308,6 +308,9 @@ class GraphicsServer {
|
||||
// bool fullscreen);
|
||||
|
||||
private:
|
||||
// So we don't have to include app_adapter.h here for asserts.
|
||||
auto InGraphicsContext_() const -> bool;
|
||||
|
||||
// Return the next frame_def to be rendered, waiting for it to arrive if
|
||||
// necessary. this can return nullptr if no frame_defs come in within a
|
||||
// reasonable amount of time. a frame_def here *must* be rendered and
|
||||
|
||||
@ -2,19 +2,20 @@
|
||||
|
||||
#include "ballistica/base/graphics/mesh/mesh_data.h"
|
||||
|
||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||
#include "ballistica/base/graphics/renderer/renderer.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
void MeshData::Load(Renderer* renderer) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
if (!renderer_data_) {
|
||||
renderer_data_ = renderer->NewMeshData(type(), draw_type());
|
||||
}
|
||||
}
|
||||
|
||||
void MeshData::Unload(Renderer* renderer) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
if (renderer_data_) {
|
||||
renderer->DeleteMeshData(renderer_data_, type());
|
||||
renderer_data_ = nullptr;
|
||||
|
||||
@ -6,18 +6,6 @@
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
auto NinePatchMesh::BorderForRadius(float corner_radius,
|
||||
float matching_dimension,
|
||||
float other_dimension) -> float {
|
||||
// Limit the radius to no more than half the shortest side.
|
||||
corner_radius = std::min(
|
||||
corner_radius, std::min(matching_dimension, other_dimension) * 0.5f);
|
||||
if (corner_radius < 0.0001f) {
|
||||
return 0.0f;
|
||||
}
|
||||
return corner_radius / matching_dimension;
|
||||
}
|
||||
|
||||
NinePatchMesh::NinePatchMesh(float x, float y, float z, float width,
|
||||
float height, float border_left,
|
||||
float border_bottom, float border_right,
|
||||
@ -35,6 +23,7 @@ NinePatchMesh::NinePatchMesh(float x, float y, float z, float width,
|
||||
VertexSimpleFull verts[16]; // 4 vertical * 4 horizontal slices.
|
||||
uint16_t indices[54]; // 9 patches * 2 triangles * 3 verts.
|
||||
|
||||
// Vertical slices.
|
||||
float y0 = y;
|
||||
float y1 = y + border_bottom * height;
|
||||
float y2 = y + (1.0 - border_top) * height;
|
||||
@ -44,6 +33,7 @@ NinePatchMesh::NinePatchMesh(float x, float y, float z, float width,
|
||||
auto v2 = 32767;
|
||||
auto v3 = 0;
|
||||
|
||||
// Horizontal slices.
|
||||
float x0 = x;
|
||||
float x1 = x + border_left * width;
|
||||
float x2 = x + (1.0 - border_right) * width;
|
||||
@ -53,9 +43,7 @@ NinePatchMesh::NinePatchMesh(float x, float y, float z, float width,
|
||||
auto u2 = 32767;
|
||||
auto u3 = 65535;
|
||||
|
||||
int icount{};
|
||||
|
||||
// Assign all 16 positions and uvs.
|
||||
// Fill out all 16 verts.
|
||||
for (int yi = 0; yi < 4; ++yi) {
|
||||
for (int xi = 0; xi < 4; ++xi) {
|
||||
VertexSimpleFull* v = verts + yi * 4 + xi;
|
||||
@ -108,18 +96,17 @@ NinePatchMesh::NinePatchMesh(float x, float y, float z, float width,
|
||||
}
|
||||
|
||||
// Now add triangle draws for any of the 9 patches with width/height > 0.
|
||||
int icount{};
|
||||
for (int yi = 0; yi < 3; ++yi) {
|
||||
for (int xi = 0; xi < 3; ++xi) {
|
||||
VertexSimpleFull* v = verts + yi * 4 + xi;
|
||||
VertexSimpleFull* vright = v + 1;
|
||||
VertexSimpleFull* vtop = v + 4;
|
||||
|
||||
if (vright->position[0] > v->position[0]
|
||||
&& vtop->position[1] > v->position[1]) {
|
||||
indices[icount++] = yi * 4 + xi;
|
||||
indices[icount++] = yi * 4 + xi + 1;
|
||||
indices[icount++] = (yi + 1) * 4 + xi + 1;
|
||||
|
||||
indices[icount++] = yi * 4 + xi;
|
||||
indices[icount++] = (yi + 1) * 4 + xi + 1;
|
||||
indices[icount++] = (yi + 1) * 4 + xi;
|
||||
|
||||
@ -17,9 +17,19 @@ class NinePatchMesh : public MeshIndexedSimpleFull {
|
||||
float border_top);
|
||||
|
||||
/// Calculate a border value for a NinePatchMesh based on dimensions and a
|
||||
/// desired max corner radius.
|
||||
/// desired max corner radius. For calculating left or right borders,
|
||||
/// matching_dimension should be width and other_dimension should be
|
||||
/// height. For top or bottom borders it is the opposite.
|
||||
static auto BorderForRadius(float corner_radius, float matching_dimension,
|
||||
float other_dimension) -> float;
|
||||
float other_dimension) -> float {
|
||||
// Limit the radius to no more than half the shortest side.
|
||||
corner_radius = std::min(
|
||||
corner_radius, std::min(matching_dimension, other_dimension) * 0.5f);
|
||||
if (matching_dimension <= 0.0f) {
|
||||
return 0.0f;
|
||||
}
|
||||
return corner_radius / matching_dimension;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ballistica::base
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "ballistica/base/graphics/renderer/render_pass.h"
|
||||
|
||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||
#include "ballistica/base/graphics/graphics_server.h"
|
||||
#include "ballistica/base/graphics/renderer/renderer.h"
|
||||
|
||||
@ -36,7 +37,7 @@ RenderPass::RenderPass(RenderPass::Type type_in, FrameDef* frame_def_in)
|
||||
RenderPass::~RenderPass() = default;
|
||||
|
||||
void RenderPass::Render(RenderTarget* render_target, bool transparent) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
|
||||
if (explicit_bool(!DRAW_TRANSPARENT) && transparent) {
|
||||
return;
|
||||
@ -460,7 +461,7 @@ void RenderPass::Reset() {
|
||||
}
|
||||
|
||||
void RenderPass::SetFrustum(float near_val, float far_val) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
// If we're using fov-tangents:
|
||||
if (cam_use_fov_tangents_) {
|
||||
float l = near_val * cam_fov_l_tan_;
|
||||
|
||||
@ -2,12 +2,13 @@
|
||||
|
||||
#include "ballistica/base/graphics/renderer/render_target.h"
|
||||
|
||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||
#include "ballistica/base/graphics/graphics_server.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
RenderTarget::RenderTarget(Type type) : type_(type) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
}
|
||||
|
||||
RenderTarget::~RenderTarget() = default;
|
||||
|
||||
@ -2,14 +2,10 @@
|
||||
|
||||
#include "ballistica/base/graphics/renderer/renderer.h"
|
||||
|
||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||
#include "ballistica/base/graphics/graphics_server.h"
|
||||
#include "ballistica/core/core.h"
|
||||
|
||||
// FIXME: Clear out conditional stuff.
|
||||
// #if BA_OSTYPE_MACOS && BA_SDL_BUILD && !BA_SDL2_BUILD
|
||||
// #include "ballistica/core/platform/support/min_sdl.h"
|
||||
// #endif
|
||||
|
||||
#if BA_VR_BUILD
|
||||
#include "ballistica/base/graphics/graphics_vr.h"
|
||||
#endif
|
||||
@ -35,7 +31,7 @@ Renderer::~Renderer() {
|
||||
}
|
||||
|
||||
void Renderer::PreprocessFrameDef(FrameDef* frame_def) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
|
||||
// If this frame_def was made in a different quality mode than we're
|
||||
// currently in, don't attempt to render it.
|
||||
@ -96,7 +92,7 @@ void Renderer::PreprocessFrameDef(FrameDef* frame_def) {
|
||||
// actually render one of these frame_def suckers...
|
||||
// (called within the graphics thread)
|
||||
void Renderer::RenderFrameDef(FrameDef* frame_def) {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
|
||||
// If preprocess decided not to render this.
|
||||
if (!frame_def->rendering()) return;
|
||||
@ -756,7 +752,7 @@ void Renderer::UpdateDOFParams(FrameDef* frame_def) {
|
||||
}
|
||||
|
||||
void Renderer::OnScreenSizeChange() {
|
||||
assert(g_base->InGraphicsThread());
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
|
||||
// We can actually get these events at times when we don't have a valid
|
||||
// gl context, so instead of doing any GL work here let's just make a note to
|
||||
|
||||
@ -75,7 +75,11 @@ class FrameDef {
|
||||
|
||||
// How much display time does this frame-def represent.
|
||||
auto display_time_elapsed_millisecs() const -> millisecs_t {
|
||||
return display_time_elapsed_microsecs_ / 1000;
|
||||
return display_time_elapsed_millisecs_;
|
||||
}
|
||||
|
||||
auto display_time_elapsed_microsecs() const -> microsecs_t {
|
||||
return display_time_elapsed_microsecs_;
|
||||
}
|
||||
|
||||
auto quality() const -> GraphicsQuality { return quality_; }
|
||||
@ -135,6 +139,9 @@ class FrameDef {
|
||||
void set_display_time_elapsed_microsecs(microsecs_t val) {
|
||||
display_time_elapsed_microsecs_ = val;
|
||||
}
|
||||
void set_display_time_elapsed_millisecs(millisecs_t val) {
|
||||
display_time_elapsed_millisecs_ = val;
|
||||
}
|
||||
// void set_app_time_millisecs(millisecs_t val) { app_time_millisecs_ = val; }
|
||||
void set_app_time_microsecs(microsecs_t val) { app_time_microsecs_ = val; }
|
||||
|
||||
@ -242,6 +249,7 @@ class FrameDef {
|
||||
microsecs_t app_time_microsecs_{};
|
||||
microsecs_t display_time_microsecs_{};
|
||||
microsecs_t display_time_elapsed_microsecs_{};
|
||||
microsecs_t display_time_elapsed_millisecs_{};
|
||||
int64_t frame_number_{};
|
||||
int64_t frame_number_filtered_{};
|
||||
Vector3f shadow_offset_{0.0f, 0.0f, 0.0f};
|
||||
|
||||
@ -18,10 +18,8 @@ class BaseSoftInterface {
|
||||
virtual void StartApp() = 0;
|
||||
virtual auto AppManagesMainThreadEventLoop() -> bool = 0;
|
||||
virtual void RunAppToCompletion() = 0;
|
||||
// virtual void PrimeAppMainThreadEventPump() = 0;
|
||||
virtual auto InAssetsThread() const -> bool = 0;
|
||||
virtual auto InLogicThread() const -> bool = 0;
|
||||
virtual auto InGraphicsThread() const -> bool = 0;
|
||||
virtual auto InAudioThread() const -> bool = 0;
|
||||
virtual auto InBGDynamicsThread() const -> bool = 0;
|
||||
virtual auto InNetworkWriteThread() const -> bool = 0;
|
||||
|
||||
@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int {
|
||||
namespace ballistica {
|
||||
|
||||
// These are set automatically via script; don't modify them here.
|
||||
const int kEngineBuildNumber = 21397;
|
||||
const int kEngineBuildNumber = 21401;
|
||||
const char* kEngineVersion = "1.7.28";
|
||||
const int kEngineApiVersion = 8;
|
||||
|
||||
|
||||
@ -412,6 +412,41 @@ int calc_paths_(struct Context_* ctx) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int color_enabled() {
|
||||
// This logic here should line up with how the 'color_enabled' val in
|
||||
// efro.terminal is calculated.
|
||||
|
||||
// Allow explict enabling/disabling via this env var.
|
||||
const char* env = getenv("EFRO_TERMCOLORS");
|
||||
if (env && !strcmp(env, "1")) {
|
||||
return 1;
|
||||
}
|
||||
if (env && !strcmp(env, "0")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
env = getenv("TERM");
|
||||
|
||||
// If TERM is unset, don't attempt color (this is currently the case
|
||||
// in xcode).
|
||||
if (!env) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// A common way to say the terminal can't do fancy stuff like color.
|
||||
if (env && !(strcmp(env, "dumb"))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If our stdout is not attached to a terminal, go with no-color.
|
||||
if (!isatty(1)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// We seem to be a terminal with color support; let's do it!
|
||||
return 1;
|
||||
}
|
||||
|
||||
int send_command_(struct Context_* ctx, int argc, char** argv) {
|
||||
// Build a json array of our args.
|
||||
cJSON* req = cJSON_CreateObject();
|
||||
@ -420,10 +455,8 @@ int send_command_(struct Context_* ctx, int argc, char** argv) {
|
||||
cJSON_AddItemToArray(array, cJSON_CreateString(argv[i]));
|
||||
}
|
||||
cJSON_AddItemToObject(req, "a", array);
|
||||
cJSON_AddItemToObject(req, "t",
|
||||
isatty(1) ? cJSON_CreateTrue() : cJSON_CreateFalse());
|
||||
cJSON_AddItemToObject(req, "t",
|
||||
isatty(1) ? cJSON_CreateTrue() : cJSON_CreateFalse());
|
||||
cJSON_AddItemToObject(
|
||||
req, "c", color_enabled() ? cJSON_CreateTrue() : cJSON_CreateFalse());
|
||||
char* json_out = cJSON_Print(req);
|
||||
|
||||
// Send our command.
|
||||
@ -466,7 +499,6 @@ int handle_response_(const struct Context_* ctx) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
cJSON* result_dict = cJSON_Parse(inbuf);
|
||||
|
||||
if (!result_dict) {
|
||||
@ -474,7 +506,7 @@ int handle_response_(const struct Context_* ctx) {
|
||||
stderr,
|
||||
"Error: pcommandbatch client %s_%d (pid %d): failed to parse result "
|
||||
"value: %s\n",
|
||||
ctx->instance_prefix, ctx->instance_num, ctx->pid, inbuf);
|
||||
ctx->instance_prefix, ctx->instance_num, ctx->pid, inbuf);
|
||||
free(inbuf);
|
||||
return -1;
|
||||
} else {
|
||||
|
||||
@ -71,12 +71,19 @@ def _default_color_enabled() -> bool:
|
||||
"""Return whether we enable ANSI color codes by default."""
|
||||
import platform
|
||||
|
||||
# If we're not attached to a terminal, go with no-color.
|
||||
# If our stdout is not attached to a terminal, go with no-color.
|
||||
if not sys.__stdout__.isatty():
|
||||
return False
|
||||
|
||||
# Another common way to say the terminal can't do fancy stuff like color:
|
||||
if os.environ.get('TERM') == 'dumb':
|
||||
termenv = os.environ.get('TERM')
|
||||
|
||||
# If TERM is unset, don't attempt color (this is currently the case
|
||||
# in xcode).
|
||||
if termenv is None:
|
||||
return False
|
||||
|
||||
# A common way to say the terminal can't do fancy stuff like color.
|
||||
if termenv == 'dumb':
|
||||
return False
|
||||
|
||||
# On windows, try to enable ANSI color mode.
|
||||
|
||||
@ -331,8 +331,8 @@ class Server:
|
||||
argv: list[str] = reqdata['a']
|
||||
assert isinstance(argv, list)
|
||||
assert all(isinstance(i, str) for i in argv)
|
||||
isatty: bool = reqdata['t']
|
||||
assert isinstance(isatty, bool)
|
||||
color_enabled: bool = reqdata['c']
|
||||
assert isinstance(color_enabled, bool)
|
||||
|
||||
print(
|
||||
f'pcommandbatch server {self._instance} (pid {self._pid})'
|
||||
@ -345,7 +345,9 @@ class Server:
|
||||
# client. ideally should expand the client-side logic to
|
||||
# exactly match what efro.terminal.Clr does locally.
|
||||
clr: type[efro.terminal.ClrBase] = (
|
||||
efro.terminal.ClrAlways if isatty else efro.terminal.ClrNever
|
||||
efro.terminal.ClrAlways
|
||||
if color_enabled
|
||||
else efro.terminal.ClrNever
|
||||
)
|
||||
|
||||
try:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user