mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-12-08 20:58:41 +00:00
add null gpu notice (#3768)
This commit is contained in:
@@ -617,6 +617,7 @@ set(COMPANION_LIBS src/core/libraries/companion/companion_httpd.cpp
|
||||
)
|
||||
set(DEV_TOOLS src/core/devtools/layer.cpp
|
||||
src/core/devtools/layer.h
|
||||
src/core/devtools/layer_extra.cpp
|
||||
src/core/devtools/options.cpp
|
||||
src/core/devtools/options.h
|
||||
src/core/devtools/gcn/gcn_context_regs.cpp
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "layer.h"
|
||||
@@ -460,12 +460,12 @@ void L::Draw() {
|
||||
}
|
||||
|
||||
void L::TextCentered(const std::string& text) {
|
||||
float window_width = ImGui::GetWindowSize().x;
|
||||
float text_width = ImGui::CalcTextSize(text.c_str()).x;
|
||||
float window_width = GetWindowSize().x;
|
||||
float text_width = CalcTextSize(text.c_str()).x;
|
||||
float text_indentation = (window_width - text_width) * 0.5f;
|
||||
|
||||
ImGui::SameLine(text_indentation);
|
||||
ImGui::Text("%s", text.c_str());
|
||||
SameLine(text_indentation);
|
||||
Text("%s", text.c_str());
|
||||
}
|
||||
|
||||
namespace Overlay {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
@@ -9,18 +9,20 @@
|
||||
namespace Core::Devtools {
|
||||
|
||||
class Layer final : public ImGui::Layer {
|
||||
|
||||
static void DrawMenuBar();
|
||||
|
||||
static void DrawAdvanced();
|
||||
|
||||
static void DrawSimple();
|
||||
|
||||
public:
|
||||
static void SetupSettings();
|
||||
|
||||
void Draw() override;
|
||||
void TextCentered(const std::string& text);
|
||||
|
||||
// Must be inside a window
|
||||
static void DrawNullGpuNotice();
|
||||
|
||||
private:
|
||||
static void DrawMenuBar();
|
||||
static void DrawAdvanced();
|
||||
static void DrawSimple();
|
||||
|
||||
static void TextCentered(const std::string& text);
|
||||
};
|
||||
|
||||
} // namespace Core::Devtools
|
||||
|
||||
95
src/core/devtools/layer_extra.cpp
Normal file
95
src/core/devtools/layer_extra.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "layer.h"
|
||||
|
||||
#include "imgui/imgui_std.h"
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <numbers>
|
||||
|
||||
namespace Core::Devtools {
|
||||
|
||||
void Layer::DrawNullGpuNotice() {
|
||||
|
||||
auto* window = ImGui::GetCurrentWindow();
|
||||
if (window->SkipItems) {
|
||||
return;
|
||||
}
|
||||
|
||||
constexpr std::string_view mainNotice = "Null GPU is enabled";
|
||||
constexpr std::string_view detailsNotice =
|
||||
"Disable the nullGpu config to show the game display";
|
||||
|
||||
auto displaySize = window->Size;
|
||||
|
||||
ImVec2 targetSize = displaySize * 0.7f;
|
||||
|
||||
float minFontSize = 1.0f;
|
||||
float maxFontSize = 200.0f;
|
||||
float optimalFontSize = minFontSize;
|
||||
|
||||
static auto lastSize = ImVec2(-1, -1);
|
||||
static float lastFontSize = -1.0f;
|
||||
|
||||
auto* font = ImGui::GetIO().Fonts->Fonts[IMGUI_FONT_TEXT_BIG];
|
||||
|
||||
if (lastSize != targetSize) {
|
||||
while (maxFontSize - minFontSize > 0.1f) {
|
||||
float testFontSize = (minFontSize + maxFontSize) / 2.0f;
|
||||
|
||||
ImVec2 textSize = font->CalcTextSizeA(testFontSize, FLT_MAX, 0.0f, &mainNotice.front(),
|
||||
&mainNotice.back() + 1);
|
||||
|
||||
if (textSize.x <= targetSize.x && textSize.y <= targetSize.y) {
|
||||
optimalFontSize = testFontSize;
|
||||
minFontSize = testFontSize;
|
||||
} else {
|
||||
maxFontSize = testFontSize;
|
||||
}
|
||||
}
|
||||
lastSize = targetSize;
|
||||
lastFontSize = optimalFontSize;
|
||||
} else {
|
||||
optimalFontSize = lastFontSize;
|
||||
}
|
||||
ImVec2 textSize = font->CalcTextSizeA(optimalFontSize, FLT_MAX, 0.0f, &mainNotice.front(),
|
||||
&mainNotice.back() + 1);
|
||||
|
||||
ImVec2 textPos = (displaySize - textSize) * 0.5f + window->Pos;
|
||||
|
||||
const float scale = optimalFontSize / font->FontSize;
|
||||
double timeAnim = -std::numbers::pi * ImGui::GetTime();
|
||||
int i = 0;
|
||||
for (auto ch : mainNotice) {
|
||||
double colorTime = sin(timeAnim + i * std::numbers::pi / 6.0) / 2.0 + 0.5;
|
||||
int color = (int)(200 * colorTime) + 55;
|
||||
|
||||
double posTime = sin(timeAnim + i * std::numbers::pi / 15.0) / 2.0 + 0.5;
|
||||
|
||||
auto pos = textPos;
|
||||
pos.y += 10.0 * (posTime < 0.5 ? std::pow(2.0, 20.0 * posTime - 10.0) / 2.0
|
||||
: (2.0 - std::pow(2.0, -20.0 * posTime + 10.0)) / 2.0);
|
||||
|
||||
window->DrawList->AddText(font, optimalFontSize, pos, IM_COL32(color, color, color, 255),
|
||||
&ch, &ch + 1);
|
||||
textPos.x += font->FindGlyph(ch)->AdvanceX * scale;
|
||||
i++;
|
||||
}
|
||||
|
||||
font = ImGui::GetIO().Fonts->Fonts[IMGUI_FONT_TEXT];
|
||||
|
||||
textPos.y += textSize.y + 1.0;
|
||||
|
||||
optimalFontSize *= 0.2;
|
||||
textSize = font->CalcTextSizeA(optimalFontSize, FLT_MAX, 0.0f, &detailsNotice.front(),
|
||||
&detailsNotice.back() + 1);
|
||||
textPos.x = window->Pos.x + (window->Size.x - textSize.x) * 0.5f;
|
||||
window->DrawList->AddText(font, optimalFontSize, textPos, IM_COL32(200, 200, 200, 255),
|
||||
&detailsNotice.front(), &detailsNotice.back() + 1);
|
||||
}
|
||||
|
||||
} // namespace Core::Devtools
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/types.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <imgui.h>
|
||||
|
||||
@@ -12,6 +14,7 @@
|
||||
|
||||
#define IMGUI_FONT_TEXT 0
|
||||
#define IMGUI_FONT_MONO 1
|
||||
#define IMGUI_FONT_TEXT_BIG 2
|
||||
|
||||
namespace ImGui {
|
||||
|
||||
|
||||
@@ -76,10 +76,15 @@ void Initialize(const ::Vulkan::Instance& instance, const Frontend::WindowSDL& w
|
||||
font_cfg.OversampleV = 1;
|
||||
io.FontDefault = io.Fonts->AddFontFromMemoryCompressedTTF(
|
||||
imgui_font_notosansjp_regular_compressed_data,
|
||||
imgui_font_notosansjp_regular_compressed_size, 16.0f, &font_cfg, ranges.Data);
|
||||
imgui_font_notosansjp_regular_compressed_size, 32.0f, &font_cfg, ranges.Data);
|
||||
io.Fonts->AddFontFromMemoryCompressedTTF(imgui_font_proggyvector_regular_compressed_data,
|
||||
imgui_font_proggyvector_regular_compressed_size,
|
||||
16.0f);
|
||||
32.0f);
|
||||
io.Fonts->AddFontFromMemoryCompressedTTF(imgui_font_notosansjp_regular_compressed_data,
|
||||
imgui_font_notosansjp_regular_compressed_size, 128.0f,
|
||||
&font_cfg, ranges.Data);
|
||||
|
||||
io.FontGlobalScale = 0.5f;
|
||||
|
||||
StyleColorsDark();
|
||||
|
||||
@@ -110,7 +115,7 @@ void Initialize(const ::Vulkan::Instance& instance, const Frontend::WindowSDL& w
|
||||
dock_id = ImHashStr(label);
|
||||
|
||||
if (const auto dpi = SDL_GetWindowDisplayScale(window.GetSDLWindow()); dpi > 0.0f) {
|
||||
GetIO().FontGlobalScale = dpi;
|
||||
GetIO().FontGlobalScale *= dpi;
|
||||
}
|
||||
|
||||
std::at_quick_exit([] { SaveIniSettingsToDisk(GetIO().IniFilename); });
|
||||
|
||||
@@ -539,45 +539,48 @@ void Presenter::Present(Frame* frame, bool is_reusing_frame) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
ImGui::SetNextWindowDockID(dockId, ImGuiCond_Once);
|
||||
ImGui::Begin("Display##game_display", nullptr, ImGuiWindowFlags_NoNav);
|
||||
if (ImGui::Begin("Display##game_display", nullptr, ImGuiWindowFlags_NoNav)) {
|
||||
auto game_texture = frame->imgui_texture;
|
||||
auto game_width = frame->width;
|
||||
auto game_height = frame->height;
|
||||
|
||||
auto game_texture = frame->imgui_texture;
|
||||
auto game_width = frame->width;
|
||||
auto game_height = frame->height;
|
||||
|
||||
if (Libraries::SystemService::IsSplashVisible()) { // draw splash
|
||||
if (!splash_img.has_value()) {
|
||||
splash_img.emplace();
|
||||
auto splash_path = Common::ElfInfo::Instance().GetSplashPath();
|
||||
if (!splash_path.empty()) {
|
||||
splash_img = ImGui::RefCountedTexture::DecodePngFile(splash_path);
|
||||
if (Libraries::SystemService::IsSplashVisible()) { // draw splash
|
||||
if (!splash_img.has_value()) {
|
||||
splash_img.emplace();
|
||||
auto splash_path = Common::ElfInfo::Instance().GetSplashPath();
|
||||
if (!splash_path.empty()) {
|
||||
splash_img = ImGui::RefCountedTexture::DecodePngFile(splash_path);
|
||||
}
|
||||
}
|
||||
if (auto& splash_image = this->splash_img.value()) {
|
||||
auto [im_id, width, height] = splash_image.GetTexture();
|
||||
game_texture = im_id;
|
||||
game_width = width;
|
||||
game_height = height;
|
||||
}
|
||||
}
|
||||
if (auto& splash_image = this->splash_img.value()) {
|
||||
auto [im_id, width, height] = splash_image.GetTexture();
|
||||
game_texture = im_id;
|
||||
game_width = width;
|
||||
game_height = height;
|
||||
|
||||
ImVec2 contentArea = ImGui::GetContentRegionAvail();
|
||||
SetExpectedGameSize((s32)contentArea.x, (s32)contentArea.y);
|
||||
|
||||
const auto imgRect =
|
||||
FitImage(game_width, game_height, (s32)contentArea.x, (s32)contentArea.y);
|
||||
ImVec2 offset{
|
||||
static_cast<float>(imgRect.offset.x),
|
||||
static_cast<float>(imgRect.offset.y),
|
||||
};
|
||||
ImVec2 size{
|
||||
static_cast<float>(imgRect.extent.width),
|
||||
static_cast<float>(imgRect.extent.height),
|
||||
};
|
||||
|
||||
ImGui::SetCursorPos(ImGui::GetCursorStartPos() + offset);
|
||||
ImGui::Image(game_texture, size);
|
||||
|
||||
if (Config::nullGpu()) {
|
||||
Core::Devtools::Layer::DrawNullGpuNotice();
|
||||
}
|
||||
}
|
||||
|
||||
ImVec2 contentArea = ImGui::GetContentRegionAvail();
|
||||
SetExpectedGameSize((s32)contentArea.x, (s32)contentArea.y);
|
||||
|
||||
const auto imgRect =
|
||||
FitImage(game_width, game_height, (s32)contentArea.x, (s32)contentArea.y);
|
||||
ImVec2 offset{
|
||||
static_cast<float>(imgRect.offset.x),
|
||||
static_cast<float>(imgRect.offset.y),
|
||||
};
|
||||
ImVec2 size{
|
||||
static_cast<float>(imgRect.extent.width),
|
||||
static_cast<float>(imgRect.extent.height),
|
||||
};
|
||||
|
||||
ImGui::SetCursorPos(ImGui::GetCursorStartPos() + offset);
|
||||
ImGui::Image(game_texture, size);
|
||||
|
||||
ImGui::End();
|
||||
ImGui::PopStyleVar(3);
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
Reference in New Issue
Block a user