Almost got it linking...

This commit is contained in:
C.W. Betts
2022-12-27 15:56:31 -07:00
parent 7af6cb05c4
commit bc631e2dbb
5 changed files with 680 additions and 312 deletions
+18 -29
View File
@@ -38,10 +38,10 @@
#include "VMManager.h"
//#include "AppConfig.h"
#include "Frontend/InputManager.h"
#include "Frontend/INISettingsInterface.h"
#include "pcsx2/INISettingsInterface.h"
#include "Frontend/OpenGLHostDisplay.h"
#include "common/SettingsWrapper.h"
#include "CDVD/CDVDaccess.h"
#include "CDVD/CDVD.h"
#include "SPU2/Global.h"
#include "SPU2/SndOut.h"
#include "PAD/Host/KeyStatus.h"
@@ -84,7 +84,6 @@ PCSX2GameCore *_current;
NSString* DiscSubRegion;
std::unique_ptr<INISettingsInterface> s_base_settings_interface;
std::unique_ptr<HostDisplay> hostDisplay;
VMBootParameters params;
@@ -186,10 +185,10 @@ static NSString *binCueFix(NSString *path)
s_base_settings_interface = std::make_unique<INISettingsInterface>(std::move(pcsx2ini));
Host::Internal::SetBaseSettingsLayer(s_base_settings_interface.get());
EmuConfig = Pcsx2Config();
EmuFolders::SetDefaults();
SettingsInterface& si = *s_base_settings_interface.get();
EmuConfig = Pcsx2Config();
EmuFolders::SetDefaults(si);
si.SetUIntValue("UI", "SettingsVersion", 1);
{
@@ -301,16 +300,12 @@ static NSString *binCueFix(NSString *path)
params.fullscreen = false;
if(!hasInitialized){
hostDisplay = HostDisplay::CreateDisplayForAPI(OpenGLHostDisplay::RenderAPI::OpenGL);
g_host_display = HostDisplay::CreateForAPI(RenderAPI::OpenGL);
WindowInfo wi;
wi.type = WindowInfo::Type::MacOS;
wi.surface_width = screenRect.size.width ;
wi.surface_height = screenRect.size.height ;
hostDisplay->CreateRenderDevice(wi,
Host::GetStringSettingValue("EmuCore/GS", "Adapter", ""),
VsyncMode::Adaptive,
Host::GetBoolSettingValue("EmuCore/GS", "ThreadedPresentation", false),
Host::GetBoolSettingValue("EmuCore/GS", "UseDebugDevice", false));
g_host_display->CreateDevice(wi, VsyncMode::Adaptive);
if(VMManager::Initialize(params)){
@@ -731,11 +726,12 @@ void Host::OnSaveStateSaved(const std::string_view& filename)
{
}
void Host::OnGameChanged(const std::string& disc_path, const std::string& game_serial, const std::string& game_name, u32 game_crc)
void Host::OnGameChanged(const std::string& disc_path, const std::string& elf_override, const std::string& game_serial,
const std::string& game_name, u32 game_crc)
{
}
void Host::PumpMessagesOnCPUThread()
void Host::CPUThreadVSync()
{
}
@@ -753,41 +749,34 @@ void Host::RunOnCPUThread(std::function<void()> function, bool block)
#pragma mark Host Display
HostDisplay* Host::AcquireHostDisplay(HostDisplay::RenderAPI api)
bool Host::AcquireHostDisplay(RenderAPI api, bool clear_state_on_fail)
{
GET_CURRENT_OR_RETURN(nullptr);
GET_CURRENT_OR_RETURN(false);
[current.renderDelegate willRenderFrameOnAlternateThread];
return current->hostDisplay.get();
return g_host_display.get();
}
void Host::ReleaseHostDisplay()
void Host::ReleaseHostDisplay(bool clear_state)
{
GET_CURRENT_OR_RETURN();
if(current->hostDisplay.get()){
current->hostDisplay.reset();
if(g_host_display.get()){
g_host_display.reset();
}
}
HostDisplay* Host::GetHostDisplay()
{
GET_CURRENT_OR_RETURN(nullptr);
return current->hostDisplay.get();
}
bool Host::BeginPresentFrame(bool frame_skip)
{
GET_CURRENT_OR_RETURN(false);
return current->hostDisplay.get()->BeginPresent(frame_skip);
return g_host_display.get()->BeginPresent(frame_skip);
}
void Host::EndPresentFrame()
{
GET_CURRENT_OR_RETURN();
current->hostDisplay.get()->EndPresent();
g_host_display.get()->EndPresent();
}
int Host::PresentFrameBuffer()
+145 -101
View File
@@ -40,15 +40,13 @@
#include "GS.h"
#include "GS/GS.h"
#include "SPU2/spu2.h"
#include "USB/USB.h"
#include "StateWrapper.h"
#include "PAD/Gamepad.h"
#ifndef PCSX2_CORE
#include "gui/App.h"
#include "gui/ConsoleLogger.h"
#include "gui/SysThreads.h"
#else
#include "USB/USB.h"
#include "VMManager.h"
#ifdef ENABLE_ACHIEVEMENTS
#include "Frontend/Achievements.h"
#endif
#include "fmt/core.h"
@@ -58,23 +56,37 @@
using namespace R5900;
static tlbs s_tlb_backup[std::size(tlb)];
static void PreLoadPrep()
{
// ensure everything is in sync before we start overwriting stuff.
if (THREAD_VU1)
vu1Thread.WaitVU();
GetMTGS().WaitGS(false);
// backup current TLBs, since we're going to overwrite them all
std::memcpy(s_tlb_backup, tlb, sizeof(s_tlb_backup));
// clear protected pages, since we don't want to fault loading EE memory
mmap_ResetBlockTracking();
SysClearExecutionCache();
#ifndef PCSX2_CORE
PatchesVerboseReset();
#endif
}
static void PostLoadPrep()
{
resetCache();
// WriteCP0Status(cpuRegs.CP0.n.Status.val);
for(int i=0; i<48; i++) MapTLB(i);
for (int i = 0; i < 48; i++)
{
if (std::memcmp(&s_tlb_backup[i], &tlb[i], sizeof(tlbs)) != 0)
{
UnmapTLB(s_tlb_backup[i], i);
MapTLB(tlb[i], i);
}
}
if (EmuConfig.Gamefixes.GoemonTlbHack) GoemonPreloadTlb();
CBreakPoints::SetSkipFirst(BREAKPOINT_EE, 0);
CBreakPoints::SetSkipFirst(BREAKPOINT_IOP, 0);
@@ -85,55 +97,6 @@ static void PostLoadPrep()
// --------------------------------------------------------------------------------------
// SaveStateBase (implementations)
// --------------------------------------------------------------------------------------
#ifndef PCSX2_CORE
std::string SaveStateBase::GetSavestateFolder(int slot, bool isSavingOrLoading)
{
std::string CRCvalue(StringUtil::StdStringFromFormat("%08X", ElfCRC));
std::string serialName;
if (g_GameStarted || g_GameLoading)
{
if (DiscSerial.empty())
{
// Running homebrew/standalone ELF, return only the ELF name.
// can't use FileSystem here because it's DOS paths
const std::string::size_type pos = std::min(DiscSerial.rfind('/'), DiscSerial.rfind('\\'));
if (pos != std::string::npos)
serialName = DiscSerial.substr(pos + 1);
else
serialName = DiscSerial;
}
else
{
// Running a normal retail game
// Folder format is "SLXX-XXXX - (00000000)"
serialName = DiscSerial;
}
}
else
{
// Still inside the BIOS/not running a game (why would anyone want to do this?)
serialName = StringUtil::StdStringFromFormat("BIOS (%s v%u.%u)", BiosZone.c_str(), (BiosVersion >> 8), BiosVersion & 0xff);
CRCvalue = "None";
}
const std::string dir(StringUtil::StdStringFromFormat("%s" FS_OSPATH_SEPARATOR_STR "%s - (%s)",
g_Conf->Folders.Savestates.ToUTF8().data(), serialName.c_str(), CRCvalue.c_str()));
if (isSavingOrLoading)
{
if (!FileSystem::DirectoryExists(dir.c_str()))
{
// sstates should exist, no need to create it
FileSystem::CreateDirectoryPath(dir.c_str(), false);
}
}
return Path::Combine(dir, StringUtil::StdStringFromFormat("%s (%s).%02d.p2s",
serialName.c_str(), CRCvalue.c_str(), slot));
}
#endif
SaveStateBase::SaveStateBase( SafeArray<u8>& memblock )
{
Init( &memblock );
@@ -189,12 +152,12 @@ SaveStateBase& SaveStateBase::FreezeBios()
// Check the BIOS, and issue a warning if the bios for this state
// doesn't match the bios currently being used (chances are it'll still
// work fine, but some games are very picky).
u32 bioscheck = BiosChecksum;
char biosdesc[256];
memzero( biosdesc );
memcpy( biosdesc, BiosDescription.c_str(), std::min( sizeof(biosdesc), BiosDescription.length() ) );
Freeze( bioscheck );
Freeze( biosdesc );
@@ -209,15 +172,17 @@ SaveStateBase& SaveStateBase::FreezeBios()
biosdesc, bioscheck
);
}
return *this;
}
SaveStateBase& SaveStateBase::FreezeInternals()
{
const u32 previousCRC = ElfCRC;
// Print this until the MTVU problem in gifPathFreeze is taken care of (rama)
if (THREAD_VU1) Console.Warning("MTVU speedhack is enabled, saved states may not be stable");
// Second Block - Various CPU Registers and States
// -----------------------------------------------
FreezeTag( "cpuRegs" );
@@ -235,19 +200,27 @@ SaveStateBase& SaveStateBase::FreezeInternals()
StringUtil::Strlcpy(localDiscSerial, DiscSerial.c_str(), sizeof(localDiscSerial));
Freeze(localDiscSerial);
if (IsLoading())
{
DiscSerial = localDiscSerial;
if (ElfCRC != previousCRC)
{
// HACK: LastELF isn't in the save state... Load it before we go too far into restoring state.
// When we next bump save states, we should include it. We need this for achievements, because
// we want to load and activate achievements before restoring any of their tracked state.
if (const std::string& elf_override = VMManager::Internal::GetElfOverride(); !elf_override.empty())
cdvdReloadElfInfo(fmt::format("host:{}", elf_override));
else
cdvdReloadElfInfo();
}
}
// Third Block - Cycle Timers and Events
// -------------------------------------
FreezeTag( "Cycles" );
Freeze(EEsCycle);
Freeze(EEoCycle);
Freeze(iopCycleEE);
Freeze(iopBreak);
Freeze(g_nextEventCycle);
Freeze(g_iopNextEventCycle);
Freeze(s_iLastCOP0Cycle);
Freeze(s_iLastPERFCycle);
Freeze(nextCounter);
Freeze(nextsCounter);
Freeze(psxNextsCounter);
@@ -376,20 +349,13 @@ struct SysState_Component
static int SysState_MTGSFreeze(FreezeAction mode, freezeData* fP)
{
#ifndef PCSX2_CORE
ScopedCoreThreadPause paused_core;
#endif
MTGS_FreezeData sstate = { fP, 0 };
GetMTGS().Freeze(mode, sstate);
#ifndef PCSX2_CORE
paused_core.AllowResume();
#endif
return sstate.retval;
}
static constexpr SysState_Component SPU2{ "SPU2", SPU2freeze };
static constexpr SysState_Component PAD_{ "PAD", PADfreeze };
static constexpr SysState_Component USB{ "USB", USBfreeze };
static constexpr SysState_Component GS{ "GS", SysState_MTGSFreeze };
@@ -409,6 +375,9 @@ static void SysState_ComponentFreezeOutRoot(void* dest, SysState_Component comp)
static void SysState_ComponentFreezeIn(zip_file_t* zf, SysState_Component comp)
{
if (!zf)
return;
freezeData fP = { 0, nullptr };
if (comp.freeze(FreezeAction::Size, &fP) != 0)
fP.size = 0;
@@ -435,6 +404,43 @@ static void SysState_ComponentFreezeOut(SaveStateBase& writer, SysState_Componen
return;
}
static void SysState_ComponentFreezeInNew(zip_file_t* zf, const char* name, bool(*do_state_func)(StateWrapper&))
{
// TODO: We could decompress on the fly here for a little bit more speed.
std::vector<u8> data;
if (zf)
{
std::optional<std::vector<u8>> optdata(ReadBinaryFileInZip(zf));
if (optdata.has_value())
data = std::move(optdata.value());
}
StateWrapper::ReadOnlyMemoryStream stream(data.empty() ? nullptr : data.data(), data.size());
StateWrapper sw(&stream, StateWrapper::Mode::Read, g_SaveVersion);
// TODO: Get rid of the bloody exceptions.
if (!do_state_func(sw))
throw std::runtime_error(fmt::format(" * {}: Error loading state!", name));
}
static void SysState_ComponentFreezeOutNew(SaveStateBase& writer, const char* name, u32 reserve, bool (*do_state_func)(StateWrapper&))
{
StateWrapper::VectorMemoryStream stream(reserve);
StateWrapper sw(&stream, StateWrapper::Mode::Write, g_SaveVersion);
// TODO: Get rid of the bloody exceptions.
if (!do_state_func(sw))
throw std::runtime_error(fmt::format(" * {}: Error saving state!", name));
const int size = static_cast<int>(stream.GetBuffer().size());
if (size > 0)
{
writer.PrepBlock(size);
std::memcpy(writer.GetBlockPtr(), stream.GetBuffer().data(), size);
writer.CommitBlock(size);
}
}
// --------------------------------------------------------------------------------------
// BaseSavestateEntry
// --------------------------------------------------------------------------------------
@@ -606,8 +612,8 @@ public:
virtual ~SavestateEntry_USB() = default;
const char* GetFilename() const { return "USB.bin"; }
void FreezeIn(zip_file_t* zf) const { return SysState_ComponentFreezeIn(zf, USB); }
void FreezeOut(SaveStateBase& writer) const { return SysState_ComponentFreezeOut(writer, USB); }
void FreezeIn(zip_file_t* zf) const { return SysState_ComponentFreezeInNew(zf, "USB", &USB::DoState); }
void FreezeOut(SaveStateBase& writer) const { return SysState_ComponentFreezeOutNew(writer, "USB", 16 * 1024, &USB::DoState); }
bool IsRequired() const { return false; }
};
@@ -633,7 +639,44 @@ public:
bool IsRequired() const { return true; }
};
#ifdef ENABLE_ACHIEVEMENTS
class SaveStateEntry_Achievements : public BaseSavestateEntry
{
virtual ~SaveStateEntry_Achievements() override = default;
const char* GetFilename() const override { return "Achievements.bin"; }
void FreezeIn(zip_file_t* zf) const override
{
if (!Achievements::IsActive())
return;
std::optional<std::vector<u8>> data;
if (zf)
data = ReadBinaryFileInZip(zf);
if (data.has_value() && !data->empty())
Achievements::LoadState(data->data(), data->size());
else
Achievements::LoadState(nullptr, 0);
}
void FreezeOut(SaveStateBase& writer) const override
{
if (!Achievements::IsActive())
return;
std::vector<u8> data(Achievements::SaveState());
if (!data.empty())
{
writer.PrepBlock(static_cast<int>(data.size()));
std::memcpy(writer.GetBlockPtr(), data.data(), data.size());
writer.CommitBlock(static_cast<int>(data.size()));
}
}
bool IsRequired() const override { return false; }
};
#endif
// (cpuRegs, iopRegs, VPU/GIF/DMAC structures should all remain as part of a larger unified
// block, since they're all PCSX2-dependent and having separate files in the archie for them
@@ -651,22 +694,16 @@ static const std::unique_ptr<BaseSavestateEntry> SavestateEntries[] = {
std::unique_ptr<BaseSavestateEntry>(new SavestateEntry_VU0prog),
std::unique_ptr<BaseSavestateEntry>(new SavestateEntry_VU1prog),
std::unique_ptr<BaseSavestateEntry>(new SavestateEntry_SPU2),
#ifndef PCSX2_CORE
std::unique_ptr<BaseSavestateEntry>(new SavestateEntry_USB),
#endif
std::unique_ptr<BaseSavestateEntry>(new SavestateEntry_PAD),
std::unique_ptr<BaseSavestateEntry>(new SavestateEntry_GS),
#ifdef ENABLE_ACHIEVEMENTS
std::unique_ptr<BaseSavestateEntry>(new SaveStateEntry_Achievements),
#endif
};
std::unique_ptr<ArchiveEntryList> SaveState_DownloadState()
{
#ifndef PCSX2_CORE
if (!GetCoreThread().HasActiveMachine())
throw Exception::RuntimeError()
.SetDiagMsg("SysExecEvent_DownloadState: Cannot freeze/download an invalid VM state!")
.SetUserMsg("There is no active virtual machine state to download or save.");
#endif
std::unique_ptr<ArchiveEntryList> destlist = std::make_unique<ArchiveEntryList>(new VmStateBuffer("Zippable Savestate"));
memSavingState saveme(destlist->GetBuffer());
@@ -697,16 +734,17 @@ std::unique_ptr<SaveStateScreenshotData> SaveState_SaveScreenshot()
static constexpr u32 SCREENSHOT_WIDTH = 640;
static constexpr u32 SCREENSHOT_HEIGHT = 480;
std::vector<u32> pixels(SCREENSHOT_WIDTH * SCREENSHOT_HEIGHT);
if (!GetMTGS().SaveMemorySnapshot(SCREENSHOT_WIDTH, SCREENSHOT_HEIGHT, &pixels))
u32 width, height;
std::vector<u32> pixels;
if (!GetMTGS().SaveMemorySnapshot(SCREENSHOT_WIDTH, SCREENSHOT_HEIGHT, true, false, &width, &height, &pixels))
{
// saving failed for some reason, device lost?
return nullptr;
}
std::unique_ptr<SaveStateScreenshotData> data = std::make_unique<SaveStateScreenshotData>();
data->width = SCREENSHOT_WIDTH;
data->height = SCREENSHOT_HEIGHT;
data->width = width;
data->height = height;
data->pixels = std::move(pixels);
return data;
}
@@ -970,17 +1008,15 @@ static void CheckVersion(const std::string& filename, zip_t* zf)
if (savever > g_SaveVersion)
throw Exception::SaveStateLoadError(filename)
.SetDiagMsg(fmt::format("Savestate uses an unsupported or unknown savestate version.\n(PCSX2 ver={:x}, state ver={:x})", g_SaveVersion, savever))
.SetUserMsg("Cannot load this savestate. The state is an unsupported version.");
.SetUserMsg("Cannot load this savestate. The state is an unsupported version.\nOption 1: Download an older PCSX2 version from pcsx2.net and make a memcard save like on the physical PS2.\nOption 2: Delete the savestates.");
// check for a "minor" version incompatibility; which happens if the savestate being loaded is a newer version
// than the emulator recognizes. 99% chance that trying to load it will just corrupt emulation or crash.
if ((savever >> 16) != (g_SaveVersion >> 16))
throw Exception::SaveStateLoadError(filename)
.SetDiagMsg(fmt::format("Savestate uses an unknown savestate version.\n(PCSX2 ver={:x}, state ver={:x})", g_SaveVersion, savever))
.SetUserMsg("Cannot load this savestate. The state is an unsupported version.");
}
.SetUserMsg("Cannot load this savestate. The state is an unsupported version.\nOption 1: Download an older PCSX2 version from pcsx2.net and make a memcard save like on the physical PS2.\nOption 2: Delete the savestates.");}
static zip_int64_t CheckFileExistsInState(zip_t* zf, const char* name)
static zip_int64_t CheckFileExistsInState(zip_t* zf, const char* name, bool required)
{
zip_int64_t index = zip_name_locate(zf, name, /*ZIP_FL_NOCASE*/ 0);
if (index >= 0)
@@ -989,7 +1025,11 @@ static zip_int64_t CheckFileExistsInState(zip_t* zf, const char* name)
return index;
}
Console.WriteLn(Color_Red, " ... not found '%s'!", name);
if (required)
Console.WriteLn(Color_Red, " ... not found '%s'!", name);
else
DevCon.WriteLn(Color_Red, " ... not found '%s'!", name);
return index;
}
@@ -1028,15 +1068,16 @@ void SaveState_UnzipFromDisk(const std::string& filename)
CheckVersion(filename, zf.get());
// check that all parts are included
const s64 internal_index = CheckFileExistsInState(zf.get(), EntryFilename_InternalStructures);
const s64 internal_index = CheckFileExistsInState(zf.get(), EntryFilename_InternalStructures, true);
s64 entryIndices[std::size(SavestateEntries)];
// Log any parts and pieces that are missing, and then generate an exception.
bool throwIt = (internal_index < 0);
for (u32 i = 0; i < std::size(SavestateEntries); i++)
{
entryIndices[i] = CheckFileExistsInState(zf.get(), SavestateEntries[i]->GetFilename());
if (entryIndices[i] < 0 && SavestateEntries[i]->IsRequired())
const bool required = SavestateEntries[i]->IsRequired();
entryIndices[i] = CheckFileExistsInState(zf.get(), SavestateEntries[i]->GetFilename(), required);
if (entryIndices[i] < 0 && required)
throwIt = true;
}
@@ -1051,7 +1092,10 @@ void SaveState_UnzipFromDisk(const std::string& filename)
for (u32 i = 0; i < std::size(SavestateEntries); ++i)
{
if (entryIndices[i] < 0)
{
SavestateEntries[i]->FreezeIn(nullptr);
continue;
}
auto zff = zip_fopen_index_managed(zf.get(), entryIndices[i], 0);
if (!zff)
+30 -10
View File
@@ -36,25 +36,25 @@ namespace GL
ContextAGL::~ContextAGL()
{
CleanupView();
if (m_opengl_module_handle)
dlclose(m_opengl_module_handle);
}
std::unique_ptr<Context> ContextAGL::Create(const WindowInfo& wi, const Version* versions_to_try,
size_t num_versions_to_try)
std::unique_ptr<Context> ContextAGL::Create(const WindowInfo& wi, gsl::span<const Version> versions_to_try)
{
std::unique_ptr<ContextAGL> context = std::make_unique<ContextAGL>(wi);
if (!context->Initialize(versions_to_try, num_versions_to_try))
if (!context->Initialize(versions_to_try))
return nullptr;
return context;
}
bool ContextAGL::Initialize(const Version* versions_to_try, size_t num_versions_to_try)
bool ContextAGL::Initialize(gsl::span<const Version> versions_to_try)
{
MakeCurrent();
for (size_t i = 0; i < num_versions_to_try; i++)
for (const Version& cv : versions_to_try)
{
const Version& cv = versions_to_try[i];
if (cv.profile == Profile::NoProfile && CreateContext(nullptr, NSOpenGLProfileVersionLegacy, true))
{
// we already have the dummy context, so just use that
@@ -89,8 +89,8 @@ namespace GL
bool ContextAGL::ChangeSurface(const WindowInfo& new_wi)
{
m_wi.surface_width = new_wi.surface_width;
m_wi.surface_height = new_wi.surface_height;
m_wi = new_wi;
BindContextToView();
return true;
}
@@ -101,6 +101,26 @@ namespace GL
bool ContextAGL::UpdateDimensions()
{
if (![NSThread isMainThread])
{
bool ret;
dispatch_sync(dispatch_get_main_queue(), [this, &ret]{ ret = UpdateDimensions(); });
return ret;
}
const NSSize window_size = [m_view frame].size;
const CGFloat window_scale = [[m_view window] backingScaleFactor];
const u32 new_width = static_cast<u32>(window_size.width * window_scale);
const u32 new_height = static_cast<u32>(window_size.height * window_scale);
if (m_wi.surface_width == new_width && m_wi.surface_height == new_height)
return false;
m_wi.surface_width = new_width;
m_wi.surface_height = new_height;
[m_context update];
return true;
}
+30 -43
View File
@@ -22,7 +22,6 @@
#include "common/ScopedGuard.h"
#include "common/StringUtil.h"
#include "common/GL/Program.h"
#include <array>
#include <tuple>
@@ -62,22 +61,22 @@ OpenGLHostDisplay::~OpenGLHostDisplay()
}
}
HostDisplay::RenderAPI OpenGLHostDisplay::GetRenderAPI() const
RenderAPI OpenGLHostDisplay::GetRenderAPI() const
{
return m_gl_context->IsGLES() ? RenderAPI::OpenGLES : RenderAPI::OpenGL;
}
void* OpenGLHostDisplay::GetRenderDevice() const
void* OpenGLHostDisplay::GetDevice() const
{
return nullptr;
}
void* OpenGLHostDisplay::GetRenderContext() const
void* OpenGLHostDisplay::GetContext() const
{
return m_gl_context.get();
}
void* OpenGLHostDisplay::GetRenderSurface() const
void* OpenGLHostDisplay::GetSurface() const
{
return nullptr;
}
@@ -87,6 +86,9 @@ std::unique_ptr<HostDisplayTexture> OpenGLHostDisplay::CreateTexture(u32 width,
// clear error
glGetError();
// don't worry, I'm planning on removing this eventually - we'll use GSTexture instead.
glActiveTexture(GL_TEXTURE7);
GLuint id;
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
@@ -102,6 +104,8 @@ std::unique_ptr<HostDisplayTexture> OpenGLHostDisplay::CreateTexture(u32 width,
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
}
glActiveTexture(GL_TEXTURE0);
GLenum error = glGetError();
if (error != GL_NO_ERROR)
{
@@ -115,37 +119,20 @@ std::unique_ptr<HostDisplayTexture> OpenGLHostDisplay::CreateTexture(u32 width,
void OpenGLHostDisplay::UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* texture_data, u32 texture_data_stride)
{
OpenGLHostDisplayTexture* tex = static_cast<OpenGLHostDisplayTexture*>(texture);
glActiveTexture(GL_TEXTURE7);
GLint alignment;
if (texture_data_stride & 1)
alignment = 1;
else if (texture_data_stride & 2)
alignment = 2;
else
alignment = 4;
GLint old_texture_binding = 0, old_alignment = 0, old_row_length = 0;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_texture_binding);
glBindTexture(GL_TEXTURE_2D, tex->GetGLID());
glGetIntegerv(GL_UNPACK_ALIGNMENT, &old_alignment);
glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
glGetIntegerv(GL_UNPACK_ROW_LENGTH, &old_row_length);
glPixelStorei(GL_UNPACK_ROW_LENGTH, texture_data_stride / sizeof(u32));
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA8, GL_UNSIGNED_BYTE, texture_data);
glPixelStorei(GL_UNPACK_ROW_LENGTH, old_row_length);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, old_alignment);
glBindTexture(GL_TEXTURE_2D, old_texture_binding);
glActiveTexture(GL_TEXTURE0);
}
void OpenGLHostDisplay::SetVSync(VsyncMode mode)
{
if (m_gl_context->GetWindowInfo().type == WindowInfo::Type::Surfaceless)
if (m_vsync_mode == mode || m_gl_context->GetWindowInfo().type == WindowInfo::Type::Surfaceless)
return;
// Window framebuffer has to be bound to call SetSwapInterval.
@@ -157,6 +144,7 @@ void OpenGLHostDisplay::SetVSync(VsyncMode mode)
m_gl_context->SetSwapInterval(static_cast<s32>(mode != VsyncMode::Off));
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, current_fbo);
m_vsync_mode = mode;
}
const char* OpenGLHostDisplay::GetGLSLVersionString() const
@@ -190,17 +178,17 @@ std::string OpenGLHostDisplay::GetGLSLVersionHeader() const
return header;
}
bool OpenGLHostDisplay::HasRenderDevice() const
bool OpenGLHostDisplay::HasDevice() const
{
return static_cast<bool>(m_gl_context);
}
bool OpenGLHostDisplay::HasRenderSurface() const
bool OpenGLHostDisplay::HasSurface() const
{
return m_window_info.type != WindowInfo::Type::Surfaceless;
}
bool OpenGLHostDisplay::CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, VsyncMode vsync, bool threaded_presentation, bool debug_device)
bool OpenGLHostDisplay::CreateDevice(const WindowInfo& wi, VsyncMode vsync)
{
m_gl_context = GL::Context::Create(wi);
if (!m_gl_context)
@@ -217,8 +205,11 @@ bool OpenGLHostDisplay::CreateRenderDevice(const WindowInfo& wi, std::string_vie
return true;
}
bool OpenGLHostDisplay::InitializeRenderDevice(std::string_view shader_cache_directory, bool debug_device)
bool OpenGLHostDisplay::SetupDevice()
{
// We do use 8-bit formats, and higher alignment for 32-bit formats won't hurt anything.
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
SetSwapInterval();
GL::Program::ResetLastProgram();
return true;
@@ -230,7 +221,7 @@ void OpenGLHostDisplay::SetSwapInterval()
m_gl_context->SetSwapInterval(interval);
}
bool OpenGLHostDisplay::MakeRenderContextCurrent()
bool OpenGLHostDisplay::MakeCurrent()
{
if (!m_gl_context->MakeCurrent())
{
@@ -242,12 +233,12 @@ bool OpenGLHostDisplay::MakeRenderContextCurrent()
return true;
}
bool OpenGLHostDisplay::DoneRenderContextCurrent()
bool OpenGLHostDisplay::DoneCurrent()
{
return m_gl_context->DoneCurrent();
}
bool OpenGLHostDisplay::ChangeRenderWindow(const WindowInfo& new_wi)
bool OpenGLHostDisplay::ChangeWindow(const WindowInfo& new_wi)
{
pxAssert(m_gl_context);
@@ -269,7 +260,7 @@ bool OpenGLHostDisplay::ChangeRenderWindow(const WindowInfo& new_wi)
return true;
}
void OpenGLHostDisplay::ResizeRenderWindow(s32 new_window_width, s32 new_window_height, float new_window_scale)
void OpenGLHostDisplay::ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale)
{
if (!m_gl_context)
return;
@@ -313,7 +304,7 @@ HostDisplay::AdapterAndModeList OpenGLHostDisplay::GetAdapterAndModeList()
return aml;
}
void OpenGLHostDisplay::DestroyRenderSurface()
void OpenGLHostDisplay::DestroySurface()
{
if (!m_gl_context)
return;
@@ -364,11 +355,8 @@ bool OpenGLHostDisplay::BeginPresent(bool frame_skip)
void OpenGLHostDisplay::EndPresent()
{
// clear out pipeline bindings, since imgui doesn't use them
glBindProgramPipeline(0);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_STENCIL_TEST);
glActiveTexture(GL_TEXTURE0);
GL::Program::ResetLastProgram();
@@ -401,7 +389,7 @@ void OpenGLHostDisplay::DestroyTimestampQueries()
if (m_timestamp_query_started)
{
const auto EndQuery = gles ? glEndQueryEXT : glEndQuery;
EndQuery(m_timestamp_queries[m_write_timestamp_query]);
EndQuery(GL_TIME_ELAPSED);
}
DeleteQueries(static_cast<u32>(m_timestamp_queries.size()), m_timestamp_queries.data());
@@ -440,7 +428,6 @@ void OpenGLHostDisplay::PopTimestampQuery()
GLint available = 0;
GetQueryObjectiv(m_timestamp_queries[m_read_timestamp_query], GL_QUERY_RESULT_AVAILABLE, &available);
pxAssert(m_read_timestamp_query != m_write_timestamp_query);
if (!available)
break;
@@ -452,8 +439,7 @@ void OpenGLHostDisplay::PopTimestampQuery()
m_waiting_timestamp_queries--;
}
// delay ending the current query until we've read back some
if (m_timestamp_query_started && m_waiting_timestamp_queries < (NUM_TIMESTAMP_QUERIES - 1))
if (m_timestamp_query_started)
{
const auto EndQuery = gles ? glEndQueryEXT : glEndQuery;
EndQuery(GL_TIME_ELAPSED);
@@ -466,7 +452,7 @@ void OpenGLHostDisplay::PopTimestampQuery()
void OpenGLHostDisplay::KickTimestampQuery()
{
if (m_timestamp_query_started)
if (m_timestamp_query_started || m_waiting_timestamp_queries == NUM_TIMESTAMP_QUERIES)
return;
const bool gles = m_gl_context->IsGLES();
@@ -499,3 +485,4 @@ float OpenGLHostDisplay::GetAndResetAccumulatedGPUTime()
m_accumulated_gpu_time = 0.0f;
return value;
}
File diff suppressed because it is too large Load Diff