mirror of
https://github.com/open-goal/jak-project.git
synced 2024-11-23 22:29:53 +00:00
61c4fc4b91
Fixes #2983
223 lines
6.5 KiB
C++
223 lines
6.5 KiB
C++
/*!
|
|
* @file gfx.cpp
|
|
* Graphics component for the runtime. Abstraction layer for the main graphics routines.
|
|
*/
|
|
|
|
#include "gfx.h"
|
|
|
|
#include <cstdio>
|
|
#include <functional>
|
|
#include <utility>
|
|
|
|
#include "display.h"
|
|
|
|
#include "common/global_profiler/GlobalProfiler.h"
|
|
#include "common/log/log.h"
|
|
#include "common/symbols.h"
|
|
#include "common/util/FileUtil.h"
|
|
#include "common/util/json_util.h"
|
|
|
|
#include "game/common/file_paths.h"
|
|
#include "game/kernel/common/kmachine.h"
|
|
#include "game/kernel/common/kscheme.h"
|
|
#include "game/runtime.h"
|
|
#include "pipelines/opengl.h"
|
|
|
|
namespace Gfx {
|
|
|
|
std::function<void()> vsync_callback;
|
|
GfxGlobalSettings g_global_settings;
|
|
game_settings::DebugSettings g_debug_settings;
|
|
|
|
const GfxRendererModule* GetRenderer(GfxPipeline pipeline) {
|
|
switch (pipeline) {
|
|
case GfxPipeline::Invalid:
|
|
lg::error("Requested invalid renderer", fmt::underlying(pipeline));
|
|
return NULL;
|
|
case GfxPipeline::OpenGL:
|
|
return &gRendererOpenGL;
|
|
default:
|
|
lg::error("Requested unknown renderer {}", fmt::underlying(pipeline));
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
void SetRenderer(GfxPipeline pipeline) {
|
|
g_global_settings.renderer = GetRenderer(pipeline);
|
|
}
|
|
|
|
const GfxRendererModule* GetCurrentRenderer() {
|
|
return g_global_settings.renderer;
|
|
}
|
|
|
|
u32 Init(GameVersion version) {
|
|
lg::info("GFX Init");
|
|
prof().instant_event("ROOT");
|
|
|
|
g_debug_settings = game_settings::DebugSettings();
|
|
{
|
|
auto p = scoped_prof("startup::gfx::get_renderer");
|
|
g_global_settings.renderer = GetRenderer(GfxPipeline::OpenGL);
|
|
}
|
|
|
|
{
|
|
auto p = scoped_prof("startup::gfx::init_current_renderer");
|
|
if (GetCurrentRenderer()->init(g_global_settings)) {
|
|
lg::error("Gfx::Init error");
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
if (g_main_thread_id != std::this_thread::get_id()) {
|
|
lg::error("Ran Gfx::Init outside main thread. Init display elsewhere?");
|
|
} else {
|
|
{
|
|
auto p = scoped_prof("startup::gfx::init_main_display");
|
|
std::string title = "OpenGOAL";
|
|
if (g_game_version == GameVersion::Jak2) {
|
|
title += " - Work in Progress";
|
|
}
|
|
title += fmt::format(" - {} - {}", version_to_game_name_external(g_game_version),
|
|
build_revision());
|
|
Display::InitMainDisplay(640, 480, title.c_str(), g_global_settings, version);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void Loop(std::function<bool()> f) {
|
|
lg::info("GFX Loop");
|
|
while (f()) {
|
|
auto p = scoped_prof("gfx loop");
|
|
// check if we have a display
|
|
if (Display::GetMainDisplay()) {
|
|
Display::GetMainDisplay()->render();
|
|
}
|
|
}
|
|
}
|
|
|
|
u32 Exit() {
|
|
lg::info("GFX Exit");
|
|
Display::KillMainDisplay();
|
|
GetCurrentRenderer()->exit();
|
|
g_debug_settings.save_settings();
|
|
return 0;
|
|
}
|
|
|
|
void register_vsync_callback(std::function<void()> f) {
|
|
vsync_callback = std::move(f);
|
|
}
|
|
|
|
void clear_vsync_callback() {
|
|
vsync_callback = nullptr;
|
|
}
|
|
|
|
u32 vsync() {
|
|
if (GetCurrentRenderer()) {
|
|
// Inform the IOP kernel that we're vsyncing so it can run the vblank handler
|
|
if (vsync_callback != nullptr)
|
|
vsync_callback();
|
|
return GetCurrentRenderer()->vsync();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
u32 sync_path() {
|
|
if (GetCurrentRenderer()) {
|
|
return GetCurrentRenderer()->sync_path();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool CollisionRendererGetMask(GfxGlobalSettings::CollisionRendererMode mode, s64 mask_id) {
|
|
int arr_idx = mask_id / 32;
|
|
int arr_ofs = mask_id % 32;
|
|
|
|
switch (mode) {
|
|
case GfxGlobalSettings::CollisionRendererMode::Mode:
|
|
return (g_global_settings.collision_mode_mask[arr_idx] >> arr_ofs) & 1;
|
|
case GfxGlobalSettings::CollisionRendererMode::Event:
|
|
return (g_global_settings.collision_event_mask[arr_idx] >> arr_ofs) & 1;
|
|
case GfxGlobalSettings::CollisionRendererMode::Material:
|
|
return (g_global_settings.collision_material_mask[arr_idx] >> arr_ofs) & 1;
|
|
case GfxGlobalSettings::CollisionRendererMode::Skip:
|
|
if (mask_id == -1) {
|
|
return g_global_settings.collision_skip_nomask_allowed;
|
|
} else {
|
|
return g_global_settings.collision_skip_mask & mask_id;
|
|
}
|
|
case GfxGlobalSettings::CollisionRendererMode::SkipHide:
|
|
return g_global_settings.collision_skip_hide_mask & mask_id;
|
|
default:
|
|
lg::error("{} invalid params {} {}", __PRETTY_FUNCTION__, fmt::underlying(mode), mask_id);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void CollisionRendererSetMask(GfxGlobalSettings::CollisionRendererMode mode, s64 mask_id) {
|
|
int arr_idx = mask_id / 32;
|
|
int arr_ofs = mask_id % 32;
|
|
|
|
switch (mode) {
|
|
case GfxGlobalSettings::CollisionRendererMode::Mode:
|
|
g_global_settings.collision_mode_mask[arr_idx] |= 1 << arr_ofs;
|
|
break;
|
|
case GfxGlobalSettings::CollisionRendererMode::Event:
|
|
g_global_settings.collision_event_mask[arr_idx] |= 1 << arr_ofs;
|
|
break;
|
|
case GfxGlobalSettings::CollisionRendererMode::Material:
|
|
g_global_settings.collision_material_mask[arr_idx] |= 1 << arr_ofs;
|
|
break;
|
|
case GfxGlobalSettings::CollisionRendererMode::Skip:
|
|
if (mask_id == -1) {
|
|
g_global_settings.collision_skip_nomask_allowed = true;
|
|
} else {
|
|
g_global_settings.collision_skip_mask |= mask_id;
|
|
}
|
|
break;
|
|
case GfxGlobalSettings::CollisionRendererMode::SkipHide:
|
|
g_global_settings.collision_skip_hide_mask |= mask_id;
|
|
break;
|
|
default:
|
|
lg::error("{} invalid params {} {}", __PRETTY_FUNCTION__, fmt::underlying(mode), mask_id);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CollisionRendererClearMask(GfxGlobalSettings::CollisionRendererMode mode, s64 mask_id) {
|
|
int arr_idx = mask_id / 32;
|
|
int arr_ofs = mask_id % 32;
|
|
|
|
switch (mode) {
|
|
case GfxGlobalSettings::CollisionRendererMode::Mode:
|
|
g_global_settings.collision_mode_mask[arr_idx] &= ~(1 << arr_ofs);
|
|
break;
|
|
case GfxGlobalSettings::CollisionRendererMode::Event:
|
|
g_global_settings.collision_event_mask[arr_idx] &= ~(1 << arr_ofs);
|
|
break;
|
|
case GfxGlobalSettings::CollisionRendererMode::Material:
|
|
g_global_settings.collision_material_mask[arr_idx] &= ~(1 << arr_ofs);
|
|
break;
|
|
case GfxGlobalSettings::CollisionRendererMode::Skip:
|
|
if (mask_id == -1) {
|
|
g_global_settings.collision_skip_nomask_allowed = false;
|
|
} else {
|
|
g_global_settings.collision_skip_mask &= ~mask_id;
|
|
}
|
|
break;
|
|
case GfxGlobalSettings::CollisionRendererMode::SkipHide:
|
|
g_global_settings.collision_skip_hide_mask &= ~mask_id;
|
|
break;
|
|
default:
|
|
lg::error("{} invalid params {} {}", __PRETTY_FUNCTION__, fmt::underlying(mode), mask_id);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CollisionRendererSetMode(GfxGlobalSettings::CollisionRendererMode mode) {
|
|
g_global_settings.collision_mode = mode;
|
|
}
|
|
|
|
} // namespace Gfx
|