mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-13 09:39:33 +01:00
Merge pull request #10580 from hrydgard/gl-render-manager-fixes
GL render manager fixes
This commit is contained in:
18 files changed
+502
-383
No files matched your search
+3
-1
@@ -776,7 +776,9 @@ elseif(TARGET SDL2::SDL2)
|
||||
set(nativeExtra ${nativeExtra}
|
||||
SDL/SDLJoystick.h
|
||||
SDL/SDLJoystick.cpp
|
||||
SDL/SDLMain.cpp)
|
||||
SDL/SDLMain.cpp
|
||||
SDL/SDLGLGraphicsContext.cpp
|
||||
SDL/SDLVulkanGraphicsContext.cpp)
|
||||
set(nativeExtraLibs ${nativeExtraLibs} SDL2::SDL2)
|
||||
if(APPLE)
|
||||
set(nativeExtra ${nativeExtra} SDL/SDLMain.h SDL/SDLMain.mm)
|
||||
|
||||
@@ -359,7 +359,7 @@ void VulkanDeviceAllocator::ExecuteFree(FreeInfo *userdata) {
|
||||
slab.allocSizes.erase(it);
|
||||
} else {
|
||||
// Ack, a double free?
|
||||
_assert_msg_(G3D, false, "Double free? Block missing at offset %d", userdata->offset);
|
||||
_assert_msg_(G3D, false, "Double free? Block missing at offset %d", (int)userdata->offset);
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
|
||||
@@ -395,8 +395,8 @@ void PSPSaveDialog::DisplaySaveDataInfo1()
|
||||
} else {
|
||||
char title[512];
|
||||
char time[512];
|
||||
char saveTitle[512];
|
||||
char saveDetail[512];
|
||||
char saveTitle[1024];
|
||||
char saveDetail[1024];
|
||||
|
||||
char am_pm[] = "AM";
|
||||
char hour_time[10] ;
|
||||
@@ -421,27 +421,27 @@ void PSPSaveDialog::DisplaySaveDataInfo1()
|
||||
snprintf(hour_time,10,"%02d:%02d %s", hour, min, am_pm);
|
||||
}
|
||||
|
||||
snprintf(title, 512, "%s", param.GetFileInfo(currentSelectedSave).title);
|
||||
snprintf(title, sizeof(title), "%s", param.GetFileInfo(currentSelectedSave).title);
|
||||
int day = param.GetFileInfo(currentSelectedSave).modif_time.tm_mday;
|
||||
int month = param.GetFileInfo(currentSelectedSave).modif_time.tm_mon + 1;
|
||||
int year = param.GetFileInfo(currentSelectedSave).modif_time.tm_year + 1900;
|
||||
s64 sizeK = param.GetFileInfo(currentSelectedSave).size / 1024;
|
||||
switch (g_Config.iDateFormat) {
|
||||
case 1:
|
||||
snprintf(time, 512, "%d/%02d/%02d %s %lld KB", year, month, day, hour_time, sizeK);
|
||||
snprintf(time, sizeof(time), "%d/%02d/%02d %s %lld KB", year, month, day, hour_time, sizeK);
|
||||
break;
|
||||
case 2:
|
||||
snprintf(time, 512, "%02d/%02d/%d %s %lld KB", month, day, year, hour_time, sizeK);
|
||||
snprintf(time, sizeof(time), "%02d/%02d/%d %s %lld KB", month, day, year, hour_time, sizeK);
|
||||
break;
|
||||
case 3:
|
||||
snprintf(time, 512, "%02d/%02d/%d %s %lld KB", day, month, year, hour_time, sizeK);
|
||||
snprintf(time, sizeof(time), "%02d/%02d/%d %s %lld KB", day, month, year, hour_time, sizeK);
|
||||
break;
|
||||
default:
|
||||
snprintf(time, 512, "%d/%02d/%02d %s %lld KB", year, month, day, hour_time, sizeK);
|
||||
snprintf(time, sizeof(time), "%d/%02d/%02d %s %lld KB", year, month, day, hour_time, sizeK);
|
||||
}
|
||||
snprintf(saveTitle, 512, "%s", param.GetFileInfo(currentSelectedSave).saveTitle);
|
||||
snprintf(saveDetail, 512, "%s", param.GetFileInfo(currentSelectedSave).saveDetail);
|
||||
|
||||
snprintf(saveTitle, sizeof(saveTitle), "%s", param.GetFileInfo(currentSelectedSave).saveTitle);
|
||||
snprintf(saveDetail, sizeof(saveDetail), "%s", param.GetFileInfo(currentSelectedSave).saveDetail);
|
||||
|
||||
PPGeDrawRect(180, 136, 480, 137, CalcFadedColor(0xFFFFFFFF));
|
||||
std::string titleTxt = title;
|
||||
std::string timeTxt = time;
|
||||
|
||||
+24
-22
@@ -140,8 +140,7 @@ float CalculateDPIScale()
|
||||
#endif
|
||||
}
|
||||
|
||||
static int mainInternal(QApplication &a)
|
||||
{
|
||||
static int mainInternal(QApplication &a) {
|
||||
#ifdef MOBILE_DEVICE
|
||||
emugl = new MainUI();
|
||||
emugl->resize(pixel_xres, pixel_yres);
|
||||
@@ -186,15 +185,19 @@ static int mainInternal(QApplication &a)
|
||||
QScopedPointer<MainAudio> audio(new MainAudio());
|
||||
audio->run();
|
||||
#endif
|
||||
return a.exec();
|
||||
int retval = a.exec();
|
||||
delete emugl;
|
||||
return retval;
|
||||
}
|
||||
|
||||
void MainUI::EmuThreadFunc() {
|
||||
ILOG("In emu thread");
|
||||
setCurrentThreadName("Emu");
|
||||
|
||||
// There's no real requirement that NativeInit happen on this thread.
|
||||
// We just call the update/render loop here.
|
||||
// There's no real requirement that NativeInit happen on this thread, though it can't hurt...
|
||||
// We just call the update/render loop here. NativeInitGraphics should be here though.
|
||||
NativeInitGraphics(graphicsContext);
|
||||
|
||||
emuThreadState = (int)EmuThreadState::RUNNING;
|
||||
while (emuThreadState != (int)EmuThreadState::QUIT_REQUESTED) {
|
||||
#ifdef SDL
|
||||
@@ -204,6 +207,8 @@ void MainUI::EmuThreadFunc() {
|
||||
time_update();
|
||||
UpdateRunLoop();
|
||||
}
|
||||
NativeShutdownGraphics();
|
||||
|
||||
emuThreadState = (int)EmuThreadState::STOPPED;
|
||||
}
|
||||
|
||||
@@ -237,13 +242,14 @@ MainUI::MainUI(QWidget *parent):
|
||||
|
||||
MainUI::~MainUI()
|
||||
{
|
||||
if (useThread_) {
|
||||
ILOG("MainUI::Destructor");
|
||||
if (emuThreadState != (int)EmuThreadState::DISABLED) {
|
||||
ILOG("EmuThreadStop");
|
||||
EmuThreadStop();
|
||||
}
|
||||
#if defined(MOBILE_DEVICE)
|
||||
delete acc;
|
||||
#endif
|
||||
NativeShutdownGraphics();
|
||||
graphicsContext->Shutdown();
|
||||
delete graphicsContext;
|
||||
graphicsContext = nullptr;
|
||||
@@ -365,34 +371,30 @@ void MainUI::initializeGL()
|
||||
glGetError();
|
||||
#endif
|
||||
ILOG("Initializing graphics context");
|
||||
graphicsContext = new QtDummyGraphicsContext();
|
||||
NativeInitGraphics(graphicsContext);
|
||||
|
||||
// OpenGL uses a background thread to do the main processing and only renders on the gl thread.
|
||||
useThread_ = g_Config.iGPUBackend == (int)GPUBackend::OPENGL;
|
||||
graphicsContext = new QtDummyGraphicsContext();
|
||||
|
||||
if (useThread_) {
|
||||
if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL) {
|
||||
ILOG("Using thread, starting emu thread");
|
||||
EmuThreadStart();
|
||||
|
||||
graphicsContext->ThreadStart();
|
||||
} else {
|
||||
ILOG("Not using thread, backend=%d", (int)g_Config.iGPUBackend);
|
||||
}
|
||||
graphicsContext->ThreadStart();
|
||||
}
|
||||
|
||||
void MainUI::paintGL()
|
||||
{
|
||||
if (useThread_) {
|
||||
#ifdef SDL
|
||||
SDL_PumpEvents();
|
||||
#endif
|
||||
updateAccelerometer();
|
||||
if (emuThreadState == (int)EmuThreadState::DISABLED) {
|
||||
UpdateRunLoop();
|
||||
} else {
|
||||
graphicsContext->ThreadFrame();
|
||||
// Do the rest in EmuThreadFunc
|
||||
} else {
|
||||
#ifdef SDL
|
||||
SDL_PumpEvents();
|
||||
#endif
|
||||
updateAccelerometer();
|
||||
time_update();
|
||||
UpdateRunLoop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -518,8 +520,8 @@ int main(int argc, char *argv[])
|
||||
g_Config.iGPUBackend = (int)GPUBackend::OPENGL;
|
||||
|
||||
int ret = mainInternal(a);
|
||||
ILOG("Left mainInternal here.");
|
||||
|
||||
NativeShutdownGraphics();
|
||||
#ifdef SDL
|
||||
SDL_PauseAudio(1);
|
||||
SDL_CloseAudio();
|
||||
|
||||
@@ -131,8 +131,6 @@ private:
|
||||
|
||||
std::thread emuThread;
|
||||
std::atomic<int> emuThreadState;
|
||||
|
||||
bool useThread_ = false;
|
||||
};
|
||||
|
||||
extern MainUI* emugl;
|
||||
|
||||
+13
-2
@@ -72,6 +72,17 @@ void MainWindow::newFrame()
|
||||
|
||||
updateMenus();
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> lock(msgMutex_);
|
||||
while (!msgQueue_.empty()) {
|
||||
MainWindowMsg msg = msgQueue_.front();
|
||||
msgQueue_.pop();
|
||||
switch (msg) {
|
||||
case MainWindowMsg::BOOT_DONE:
|
||||
bootDone();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::updateMenus()
|
||||
@@ -128,8 +139,7 @@ void MainWindow::updateMenus()
|
||||
emit updateMenu();
|
||||
}
|
||||
|
||||
/* SLOTS */
|
||||
void MainWindow::Boot()
|
||||
void MainWindow::bootDone()
|
||||
{
|
||||
dialogDisasm = new Debugger_Disasm(currentDebugMIPS, this, this);
|
||||
if(g_Config.bShowDebuggerOnLoad)
|
||||
@@ -149,6 +159,7 @@ void MainWindow::Boot()
|
||||
updateMenus();
|
||||
}
|
||||
|
||||
/* SIGNALS */
|
||||
void MainWindow::openAct()
|
||||
{
|
||||
QString filename = QFileDialog::getOpenFileName(NULL, "Load File", g_Config.currentDirectory.c_str(), "PSP ROMs (*.pbp *.elf *.iso *.cso *.prx)");
|
||||
|
||||
+18
-5
@@ -1,5 +1,7 @@
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
#pragma once
|
||||
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
|
||||
#include <QtCore>
|
||||
#include <QMenuBar>
|
||||
@@ -21,6 +23,11 @@ extern bool g_TakeScreenshot;
|
||||
class MenuAction;
|
||||
class MenuTree;
|
||||
|
||||
// hacky, should probably use qt signals or something, but whatever..
|
||||
enum class MainWindowMsg {
|
||||
BOOT_DONE
|
||||
};
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -38,6 +45,11 @@ public:
|
||||
void ShowMemory(u32 addr);
|
||||
void updateMenus();
|
||||
|
||||
void Notify(MainWindowMsg msg) {
|
||||
std::unique_lock<std::mutex> lock(msgMutex_);
|
||||
msgQueue_.push(msg);
|
||||
}
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent *e)
|
||||
{
|
||||
@@ -54,7 +66,6 @@ signals:
|
||||
void updateMenu();
|
||||
|
||||
public slots:
|
||||
void Boot();
|
||||
void newFrame();
|
||||
|
||||
private slots:
|
||||
@@ -136,6 +147,7 @@ private slots:
|
||||
void langChanged(QAction *action) { loadLanguage(action->data().toString(), true); }
|
||||
|
||||
private:
|
||||
void bootDone();
|
||||
void SetWindowScale(int zoom);
|
||||
void SetGameTitle(QString text);
|
||||
void loadLanguage(const QString &language, bool retranslate);
|
||||
@@ -155,6 +167,9 @@ private:
|
||||
|
||||
QActionGroup *anisotropicGroup, *screenGroup, *displayLayoutGroup,
|
||||
*defaultLogGroup, *g3dLogGroup, *hleLogGroup;
|
||||
|
||||
std::queue<MainWindowMsg> msgQueue_;
|
||||
std::mutex msgMutex_;
|
||||
};
|
||||
|
||||
class MenuAction : public QAction
|
||||
@@ -275,5 +290,3 @@ public slots:
|
||||
private:
|
||||
const char *_text;
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
@@ -0,0 +1,142 @@
|
||||
#include "SDLGLGraphicsContext.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/System.h"
|
||||
#include "base/NativeApp.h"
|
||||
#include "base/display.h"
|
||||
#include "gfx_es2/gpu_features.h"
|
||||
|
||||
class GLRenderManager;
|
||||
|
||||
// Returns 0 on success.
|
||||
int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message) {
|
||||
struct GLVersionPair {
|
||||
int major;
|
||||
int minor;
|
||||
};
|
||||
GLVersionPair attemptVersions[] = {
|
||||
#ifdef USING_GLES2
|
||||
{3, 2}, {3, 1}, {3, 0}, {2, 0},
|
||||
#else
|
||||
{4, 6}, {4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0},
|
||||
{3, 3}, {3, 2}, {3, 1}, {3, 0},
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef USING_GLES2
|
||||
mode |= SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN;
|
||||
#else
|
||||
mode |= SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
|
||||
#endif
|
||||
SDL_GLContext glContext = nullptr;
|
||||
for (size_t i = 0; i < ARRAY_SIZE(attemptVersions); ++i) {
|
||||
const auto &ver = attemptVersions[i];
|
||||
// Make sure to request a somewhat modern GL context at least - the
|
||||
// latest supported by MacOS X (really, really sad...)
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, ver.major);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, ver.minor);
|
||||
#ifdef USING_GLES2
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
SetGLCoreContext(false);
|
||||
#else
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
SetGLCoreContext(true);
|
||||
#endif
|
||||
|
||||
window = SDL_CreateWindow("PPSSPP", x,y, pixel_xres, pixel_yres, mode);
|
||||
if (!window) {
|
||||
NativeShutdown();
|
||||
fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError());
|
||||
continue;
|
||||
}
|
||||
|
||||
glContext = SDL_GL_CreateContext(window);
|
||||
if (glContext != nullptr) {
|
||||
// Victory, got one.
|
||||
break;
|
||||
}
|
||||
|
||||
// Let's keep trying. To be safe, destroy the window - docs say needed to change profile.
|
||||
// in practice, it doesn't seem to matter, but maybe it differs by platform.
|
||||
SDL_DestroyWindow(window);
|
||||
}
|
||||
|
||||
if (glContext == nullptr) {
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
SetGLCoreContext(false);
|
||||
|
||||
window = SDL_CreateWindow("PPSSPP", x,y, pixel_xres, pixel_yres, mode);
|
||||
if (window == nullptr) {
|
||||
NativeShutdown();
|
||||
fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError());
|
||||
SDL_Quit();
|
||||
return 2;
|
||||
}
|
||||
|
||||
glContext = SDL_GL_CreateContext(window);
|
||||
if (glContext == nullptr) {
|
||||
NativeShutdown();
|
||||
fprintf(stderr, "SDL_GL_CreateContext failed: %s\n", SDL_GetError());
|
||||
SDL_Quit();
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USING_EGL
|
||||
EGL_Init();
|
||||
#endif
|
||||
|
||||
#ifndef USING_GLES2
|
||||
// Some core profile drivers elide certain extensions from GL_EXTENSIONS/etc.
|
||||
// glewExperimental allows us to force GLEW to search for the pointers anyway.
|
||||
if (gl_extensions.IsCoreContext) {
|
||||
glewExperimental = true;
|
||||
}
|
||||
if (GLEW_OK != glewInit()) {
|
||||
printf("Failed to initialize glew!\n");
|
||||
return 1;
|
||||
}
|
||||
// Unfortunately, glew will generate an invalid enum error, ignore.
|
||||
if (gl_extensions.IsCoreContext)
|
||||
glGetError();
|
||||
|
||||
if (GLEW_VERSION_2_0) {
|
||||
printf("OpenGL 2.0 or higher.\n");
|
||||
} else {
|
||||
printf("Sorry, this program requires OpenGL 2.0.\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Finally we can do the regular initialization.
|
||||
CheckGLExtensions();
|
||||
draw_ = Draw::T3DCreateGLContext();
|
||||
renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
||||
SetGPUBackend(GPUBackend::OPENGL);
|
||||
bool success = draw_->CreatePresets();
|
||||
assert(success);
|
||||
renderManager_->SetSwapFunction([&]() {
|
||||
#ifdef USING_EGL
|
||||
eglSwapBuffers(g_eglDisplay, g_eglSurface);
|
||||
#else
|
||||
SDL_GL_SwapWindow(window_);
|
||||
#endif
|
||||
});
|
||||
window_ = window;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SDLGLGraphicsContext::Shutdown() {
|
||||
}
|
||||
|
||||
void SDLGLGraphicsContext::ShutdownFromRenderThread() {
|
||||
delete draw_;
|
||||
draw_ = nullptr;
|
||||
|
||||
#ifdef USING_EGL
|
||||
EGL_Close();
|
||||
#else
|
||||
SDL_GL_DeleteContext(glContext);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#if !defined(__APPLE__)
|
||||
#include "SDL_syswm.h"
|
||||
#endif
|
||||
#include "SDL.h"
|
||||
|
||||
#include "thin3d/GLRenderManager.h"
|
||||
#include "gfx/gl_common.h"
|
||||
#include "Common/GraphicsContext.h"
|
||||
|
||||
class SDLGLGraphicsContext : public DummyGraphicsContext {
|
||||
public:
|
||||
SDLGLGraphicsContext() {
|
||||
}
|
||||
|
||||
// Returns 0 on success.
|
||||
int Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message);
|
||||
|
||||
void Shutdown() override;
|
||||
void ShutdownFromRenderThread() override;
|
||||
|
||||
void SwapBuffers() override {
|
||||
renderManager_->Swap();
|
||||
}
|
||||
|
||||
Draw::DrawContext *GetDrawContext() override {
|
||||
return draw_;
|
||||
}
|
||||
|
||||
void ThreadStart() override {
|
||||
renderManager_->ThreadStart();
|
||||
}
|
||||
|
||||
bool ThreadFrame() override {
|
||||
return renderManager_->ThreadFrame();
|
||||
}
|
||||
|
||||
void ThreadEnd() override {
|
||||
renderManager_->ThreadEnd();
|
||||
}
|
||||
|
||||
private:
|
||||
Draw::DrawContext *draw_ = nullptr;
|
||||
SDL_Window *window_;
|
||||
SDL_GLContext glContext = nullptr;
|
||||
GLRenderManager *renderManager_ = nullptr;
|
||||
};
|
||||
|
||||
|
||||
+30
-333
@@ -24,20 +24,15 @@ SDLJoystick *joystick = NULL;
|
||||
#include "base/logging.h"
|
||||
#include "base/timeutil.h"
|
||||
#include "ext/glslang/glslang/Public/ShaderLang.h"
|
||||
#include "gfx/gl_common.h"
|
||||
#include "gfx_es2/gpu_features.h"
|
||||
#include "input/input_state.h"
|
||||
#include "input/keycodes.h"
|
||||
#include "net/resolve.h"
|
||||
#include "base/NKCodeFromSDL.h"
|
||||
#include "util/const_map.h"
|
||||
#include "util/text/utf8.h"
|
||||
#include "util/text/parsers.h"
|
||||
#include "math/math_util.h"
|
||||
#include "thin3d/GLRenderManager.h"
|
||||
#include "thread/threadutil.h"
|
||||
#include "Common/Vulkan/VulkanContext.h"
|
||||
#include "Common/Vulkan/VulkanDebug.h"
|
||||
#include "math.h"
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
@@ -61,6 +56,9 @@ SDLJoystick *joystick = NULL;
|
||||
#include "Core/Core.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Common/GraphicsContext.h"
|
||||
#include "SDLGLGraphicsContext.h"
|
||||
#include "SDLVulkanGraphicsContext.h"
|
||||
|
||||
|
||||
GlobalUIState lastUIState = UISTATE_MENU;
|
||||
GlobalUIState GetUIState();
|
||||
@@ -72,8 +70,6 @@ static int g_QuitRequested = 0;
|
||||
static int g_DesktopWidth = 0;
|
||||
static int g_DesktopHeight = 0;
|
||||
|
||||
static VulkanLogOptions g_LogOptions;
|
||||
|
||||
#if defined(USING_EGL)
|
||||
|
||||
static EGLDisplay g_eglDisplay = NULL;
|
||||
@@ -202,318 +198,6 @@ void EGL_Close() {
|
||||
}
|
||||
#endif
|
||||
|
||||
class GLRenderManager;
|
||||
|
||||
class SDLGLGraphicsContext : public DummyGraphicsContext {
|
||||
public:
|
||||
SDLGLGraphicsContext() {
|
||||
}
|
||||
~SDLGLGraphicsContext() {
|
||||
delete draw_;
|
||||
}
|
||||
|
||||
// Returns 0 on success.
|
||||
int Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message);
|
||||
|
||||
void Shutdown() override {
|
||||
#ifdef USING_EGL
|
||||
EGL_Close();
|
||||
#else
|
||||
SDL_GL_DeleteContext(glContext);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SwapBuffers() override {
|
||||
renderManager_->Swap();
|
||||
}
|
||||
|
||||
Draw::DrawContext *GetDrawContext() override {
|
||||
return draw_;
|
||||
}
|
||||
|
||||
void ThreadStart() override {
|
||||
renderManager_->ThreadStart();
|
||||
}
|
||||
|
||||
bool ThreadFrame() override {
|
||||
return renderManager_->ThreadFrame();
|
||||
}
|
||||
|
||||
void ThreadEnd() override {
|
||||
renderManager_->ThreadEnd();
|
||||
}
|
||||
|
||||
private:
|
||||
Draw::DrawContext *draw_ = nullptr;
|
||||
SDL_Window *window_;
|
||||
SDL_GLContext glContext = nullptr;
|
||||
GLRenderManager *renderManager_ = nullptr;
|
||||
};
|
||||
|
||||
// Returns 0 on success.
|
||||
int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message) {
|
||||
struct GLVersionPair {
|
||||
int major;
|
||||
int minor;
|
||||
};
|
||||
GLVersionPair attemptVersions[] = {
|
||||
#ifdef USING_GLES2
|
||||
{3, 2}, {3, 1}, {3, 0}, {2, 0},
|
||||
#else
|
||||
{4, 6}, {4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0},
|
||||
{3, 3}, {3, 2}, {3, 1}, {3, 0},
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef USING_GLES2
|
||||
mode |= SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN;
|
||||
#else
|
||||
mode |= SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
|
||||
#endif
|
||||
SDL_GLContext glContext = nullptr;
|
||||
for (size_t i = 0; i < ARRAY_SIZE(attemptVersions); ++i) {
|
||||
const auto &ver = attemptVersions[i];
|
||||
// Make sure to request a somewhat modern GL context at least - the
|
||||
// latest supported by MacOS X (really, really sad...)
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, ver.major);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, ver.minor);
|
||||
#ifdef USING_GLES2
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
SetGLCoreContext(false);
|
||||
#else
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
SetGLCoreContext(true);
|
||||
#endif
|
||||
|
||||
window = SDL_CreateWindow("PPSSPP", x,y, pixel_xres, pixel_yres, mode);
|
||||
if (!window) {
|
||||
NativeShutdown();
|
||||
fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError());
|
||||
continue;
|
||||
}
|
||||
|
||||
glContext = SDL_GL_CreateContext(window);
|
||||
if (glContext != nullptr) {
|
||||
// Victory, got one.
|
||||
break;
|
||||
}
|
||||
|
||||
// Let's keep trying. To be safe, destroy the window - docs say needed to change profile.
|
||||
// in practice, it doesn't seem to matter, but maybe it differs by platform.
|
||||
SDL_DestroyWindow(window);
|
||||
}
|
||||
|
||||
if (glContext == nullptr) {
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
SetGLCoreContext(false);
|
||||
|
||||
window = SDL_CreateWindow("PPSSPP", x,y, pixel_xres, pixel_yres, mode);
|
||||
if (window == nullptr) {
|
||||
NativeShutdown();
|
||||
fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError());
|
||||
SDL_Quit();
|
||||
return 2;
|
||||
}
|
||||
|
||||
glContext = SDL_GL_CreateContext(window);
|
||||
if (glContext == nullptr) {
|
||||
NativeShutdown();
|
||||
fprintf(stderr, "SDL_GL_CreateContext failed: %s\n", SDL_GetError());
|
||||
SDL_Quit();
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USING_EGL
|
||||
EGL_Init();
|
||||
#endif
|
||||
|
||||
#ifndef USING_GLES2
|
||||
// Some core profile drivers elide certain extensions from GL_EXTENSIONS/etc.
|
||||
// glewExperimental allows us to force GLEW to search for the pointers anyway.
|
||||
if (gl_extensions.IsCoreContext) {
|
||||
glewExperimental = true;
|
||||
}
|
||||
if (GLEW_OK != glewInit()) {
|
||||
printf("Failed to initialize glew!\n");
|
||||
return 1;
|
||||
}
|
||||
// Unfortunately, glew will generate an invalid enum error, ignore.
|
||||
if (gl_extensions.IsCoreContext)
|
||||
glGetError();
|
||||
|
||||
if (GLEW_VERSION_2_0) {
|
||||
printf("OpenGL 2.0 or higher.\n");
|
||||
} else {
|
||||
printf("Sorry, this program requires OpenGL 2.0.\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Finally we can do the regular initialization.
|
||||
CheckGLExtensions();
|
||||
draw_ = Draw::T3DCreateGLContext();
|
||||
renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
||||
SetGPUBackend(GPUBackend::OPENGL);
|
||||
bool success = draw_->CreatePresets();
|
||||
assert(success);
|
||||
renderManager_->SetSwapFunction([&]() {
|
||||
#ifdef USING_EGL
|
||||
eglSwapBuffers(g_eglDisplay, g_eglSurface);
|
||||
#else
|
||||
SDL_GL_SwapWindow(window_);
|
||||
#endif
|
||||
});
|
||||
window_ = window;
|
||||
return 0;
|
||||
}
|
||||
|
||||
class SDLVulkanGraphicsContext : public GraphicsContext {
|
||||
public:
|
||||
SDLVulkanGraphicsContext() {}
|
||||
~SDLVulkanGraphicsContext() {
|
||||
delete draw_;
|
||||
}
|
||||
|
||||
bool Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message);
|
||||
|
||||
void Shutdown() override;
|
||||
|
||||
void SwapBuffers() override {
|
||||
// We don't do it this way.
|
||||
}
|
||||
|
||||
void Resize() override {
|
||||
/*
|
||||
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight());
|
||||
vulkan_->DestroyObjects();
|
||||
// TODO: Take from real window dimensions
|
||||
int width = 1024;
|
||||
int height = 768;
|
||||
vulkan_->ReinitSurface(width, height);
|
||||
vulkan_->InitObjects();
|
||||
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight());
|
||||
*/
|
||||
}
|
||||
|
||||
void SwapInterval(int interval) override {
|
||||
}
|
||||
void *GetAPIContext() override {
|
||||
return vulkan_;
|
||||
}
|
||||
|
||||
Draw::DrawContext *GetDrawContext() override {
|
||||
return draw_;
|
||||
}
|
||||
private:
|
||||
Draw::DrawContext *draw_ = nullptr;
|
||||
VulkanContext *vulkan_ = nullptr;
|
||||
};
|
||||
|
||||
bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message) {
|
||||
window = SDL_CreateWindow("Initializing Vulkan...", x, y, pixel_xres, pixel_yres, mode);
|
||||
if (!window) {
|
||||
fprintf(stderr, "Error creating SDL window: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
init_glslang();
|
||||
|
||||
g_LogOptions.breakOnError = true;
|
||||
g_LogOptions.breakOnWarning = true;
|
||||
g_LogOptions.msgBoxOnError = false;
|
||||
|
||||
Version gitVer(PPSSPP_GIT_VERSION);
|
||||
|
||||
vulkan_ = new VulkanContext();
|
||||
if (vulkan_->InitError().size()) {
|
||||
*error_message = vulkan_->InitError();
|
||||
delete vulkan_;
|
||||
vulkan_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
int vulkanFlags = VULKAN_FLAG_PRESENT_MAILBOX;
|
||||
// vulkanFlags |= VULKAN_FLAG_VALIDATE;
|
||||
VulkanContext::CreateInfo info{};
|
||||
info.app_name = "PPSSPP";
|
||||
info.app_ver = gitVer.ToInteger();
|
||||
info.flags = vulkanFlags;
|
||||
if (VK_SUCCESS != vulkan_->CreateInstance(info)) {
|
||||
*error_message = vulkan_->InitError();
|
||||
delete vulkan_;
|
||||
vulkan_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
vulkan_->ChooseDevice(vulkan_->GetBestPhysicalDevice());
|
||||
if (vulkan_->CreateDevice() != VK_SUCCESS) {
|
||||
*error_message = vulkan_->InitError();
|
||||
delete vulkan_;
|
||||
vulkan_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
SDL_SysWMinfo sys_info{};
|
||||
SDL_VERSION(&sys_info.version); //Set SDL version
|
||||
if (!SDL_GetWindowWMInfo(window, &sys_info)) {
|
||||
fprintf(stderr, "Error getting SDL window wm info: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
switch (sys_info.subsystem) {
|
||||
case SDL_SYSWM_X11:
|
||||
#if defined(VK_USE_PLATFORM_XLIB_KHR)
|
||||
vulkan_->InitSurface(WINDOWSYSTEM_XLIB, (void*)sys_info.info.x11.display,
|
||||
(void *)(intptr_t)sys_info.info.x11.window, pixel_xres, pixel_yres);
|
||||
#elif defined(VK_USE_PLATFORM_XCB_KHR)
|
||||
vulkan_->InitSurface(WINDOWSYSTEM_XCB, (void*)XGetXCBConnection(sys_info.info.x11.display),
|
||||
(void *)(intptr_t)sys_info.info.x11.window, pixel_xres, pixel_yres);
|
||||
#endif
|
||||
break;
|
||||
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
|
||||
case SDL_SYSWM_WAYLAND:
|
||||
vulkan_->InitSurface(WINDOWSYSTEM_WAYLAND, (void*)sys_info.info.wl.display,
|
||||
(void *)sys_info.info.wl.surface, pixel_xres, pixel_yres);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(stderr, "Vulkan subsystem %d not supported\n", sys_info.subsystem);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!vulkan_->InitObjects()) {
|
||||
*error_message = vulkan_->InitError();
|
||||
Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
draw_ = Draw::T3DCreateVulkanContext(vulkan_, false);
|
||||
SetGPUBackend(GPUBackend::VULKAN);
|
||||
bool success = draw_->CreatePresets();
|
||||
assert(success);
|
||||
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SDLVulkanGraphicsContext::Shutdown() {
|
||||
if (draw_)
|
||||
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight());
|
||||
delete draw_;
|
||||
draw_ = nullptr;
|
||||
vulkan_->WaitUntilQueueIdle();
|
||||
vulkan_->DestroyObjects();
|
||||
vulkan_->DestroyDevice();
|
||||
vulkan_->DestroyDebugMsgCallback();
|
||||
vulkan_->DestroyInstance();
|
||||
delete vulkan_;
|
||||
vulkan_ = nullptr;
|
||||
finalize_glslang();
|
||||
}
|
||||
|
||||
int getDisplayNumber(void) {
|
||||
int displayNumber = 0;
|
||||
@@ -522,8 +206,7 @@ int getDisplayNumber(void) {
|
||||
//get environment
|
||||
displayNumberStr=getenv("SDL_VIDEO_FULLSCREEN_HEAD");
|
||||
|
||||
if (displayNumberStr)
|
||||
{
|
||||
if (displayNumberStr) {
|
||||
displayNumber = atoi(displayNumberStr);
|
||||
}
|
||||
|
||||
@@ -725,21 +408,26 @@ enum class EmuThreadState {
|
||||
static std::thread emuThread;
|
||||
static std::atomic<int> emuThreadState((int)EmuThreadState::DISABLED);
|
||||
|
||||
static void EmuThreadFunc() {
|
||||
static void EmuThreadFunc(GraphicsContext *graphicsContext) {
|
||||
setCurrentThreadName("Emu");
|
||||
|
||||
// There's no real requirement that NativeInit happen on this thread.
|
||||
// We just call the update/render loop here.
|
||||
emuThreadState = (int)EmuThreadState::RUNNING;
|
||||
|
||||
NativeInitGraphics(graphicsContext);
|
||||
|
||||
while (emuThreadState != (int)EmuThreadState::QUIT_REQUESTED) {
|
||||
UpdateRunLoop();
|
||||
}
|
||||
emuThreadState = (int)EmuThreadState::STOPPED;
|
||||
|
||||
NativeShutdownGraphics();
|
||||
}
|
||||
|
||||
static void EmuThreadStart() {
|
||||
static void EmuThreadStart(GraphicsContext *context) {
|
||||
emuThreadState = (int)EmuThreadState::START_REQUESTED;
|
||||
emuThread = std::thread(&EmuThreadFunc);
|
||||
emuThread = std::thread(&EmuThreadFunc, context);
|
||||
}
|
||||
|
||||
static void EmuThreadStop() {
|
||||
@@ -923,6 +611,9 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
GraphicsContext *graphicsContext = nullptr;
|
||||
SDL_Window *window = nullptr;
|
||||
|
||||
bool useEmuThread;
|
||||
|
||||
std::string error_message;
|
||||
if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL) {
|
||||
SDLGLGraphicsContext *ctx = new SDLGLGraphicsContext();
|
||||
@@ -930,6 +621,7 @@ int main(int argc, char *argv[]) {
|
||||
printf("GL init error '%s'\n", error_message.c_str());
|
||||
}
|
||||
graphicsContext = ctx;
|
||||
useEmuThread = true;
|
||||
} else if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) {
|
||||
SDLVulkanGraphicsContext *ctx = new SDLVulkanGraphicsContext();
|
||||
if (!ctx->Init(window, x, y, mode, &error_message)) {
|
||||
@@ -943,6 +635,7 @@ int main(int argc, char *argv[]) {
|
||||
} else {
|
||||
graphicsContext = ctx;
|
||||
}
|
||||
useEmuThread = false;
|
||||
}
|
||||
|
||||
// Since we render from the main thread, there's nothing done here, but we call it to avoid confusion.
|
||||
@@ -956,9 +649,10 @@ int main(int argc, char *argv[]) {
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
#endif
|
||||
|
||||
NativeInitGraphics(graphicsContext);
|
||||
|
||||
NativeResized();
|
||||
if (!useEmuThread) {
|
||||
NativeInitGraphics(graphicsContext);
|
||||
NativeResized();
|
||||
}
|
||||
|
||||
SDL_AudioSpec fmt, ret_fmt;
|
||||
memset(&fmt, 0, sizeof(fmt));
|
||||
@@ -996,8 +690,8 @@ int main(int argc, char *argv[]) {
|
||||
int framecount = 0;
|
||||
bool mouseDown = false;
|
||||
|
||||
if (GetGPUBackend() == GPUBackend::OPENGL) {
|
||||
EmuThreadStart();
|
||||
if (useEmuThread) {
|
||||
EmuThreadStart(graphicsContext);
|
||||
}
|
||||
graphicsContext->ThreadStart();
|
||||
|
||||
@@ -1198,14 +892,16 @@ int main(int argc, char *argv[]) {
|
||||
framecount++;
|
||||
}
|
||||
|
||||
graphicsContext->ThreadEnd();
|
||||
graphicsContext->ShutdownFromRenderThread();
|
||||
|
||||
EmuThreadStop();
|
||||
|
||||
delete joystick;
|
||||
NativeShutdownGraphics();
|
||||
|
||||
if (!useEmuThread) {
|
||||
NativeShutdownGraphics();
|
||||
}
|
||||
graphicsContext->Shutdown();
|
||||
graphicsContext->ThreadEnd();
|
||||
graphicsContext->ShutdownFromRenderThread();
|
||||
NativeShutdown();
|
||||
delete graphicsContext;
|
||||
|
||||
@@ -1217,5 +913,6 @@ int main(int argc, char *argv[]) {
|
||||
#endif
|
||||
|
||||
glslang::FinalizeProcess();
|
||||
ILOG("Leaving main");
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
#include "Core/Config.h"
|
||||
#include "base/NativeApp.h"
|
||||
#include "base/display.h"
|
||||
#include "thin3d/thin3d.h"
|
||||
#include "util/text/parsers.h"
|
||||
|
||||
#include "Core/System.h"
|
||||
#include "SDLVulkanGraphicsContext.h"
|
||||
|
||||
bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message) {
|
||||
window = SDL_CreateWindow("Initializing Vulkan...", x, y, pixel_xres, pixel_yres, mode);
|
||||
if (!window) {
|
||||
fprintf(stderr, "Error creating SDL window: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
init_glslang();
|
||||
|
||||
g_LogOptions.breakOnError = true;
|
||||
g_LogOptions.breakOnWarning = true;
|
||||
g_LogOptions.msgBoxOnError = false;
|
||||
|
||||
Version gitVer(PPSSPP_GIT_VERSION);
|
||||
|
||||
vulkan_ = new VulkanContext();
|
||||
if (vulkan_->InitError().size()) {
|
||||
*error_message = vulkan_->InitError();
|
||||
delete vulkan_;
|
||||
vulkan_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
int vulkanFlags = VULKAN_FLAG_PRESENT_MAILBOX;
|
||||
// vulkanFlags |= VULKAN_FLAG_VALIDATE;
|
||||
VulkanContext::CreateInfo info{};
|
||||
info.app_name = "PPSSPP";
|
||||
info.app_ver = gitVer.ToInteger();
|
||||
info.flags = vulkanFlags;
|
||||
if (VK_SUCCESS != vulkan_->CreateInstance(info)) {
|
||||
*error_message = vulkan_->InitError();
|
||||
delete vulkan_;
|
||||
vulkan_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
vulkan_->ChooseDevice(vulkan_->GetBestPhysicalDevice());
|
||||
if (vulkan_->CreateDevice() != VK_SUCCESS) {
|
||||
*error_message = vulkan_->InitError();
|
||||
delete vulkan_;
|
||||
vulkan_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
SDL_SysWMinfo sys_info{};
|
||||
SDL_VERSION(&sys_info.version); //Set SDL version
|
||||
if (!SDL_GetWindowWMInfo(window, &sys_info)) {
|
||||
fprintf(stderr, "Error getting SDL window wm info: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
switch (sys_info.subsystem) {
|
||||
case SDL_SYSWM_X11:
|
||||
#if defined(VK_USE_PLATFORM_XLIB_KHR)
|
||||
vulkan_->InitSurface(WINDOWSYSTEM_XLIB, (void*)sys_info.info.x11.display,
|
||||
(void *)(intptr_t)sys_info.info.x11.window, pixel_xres, pixel_yres);
|
||||
#elif defined(VK_USE_PLATFORM_XCB_KHR)
|
||||
vulkan_->InitSurface(WINDOWSYSTEM_XCB, (void*)XGetXCBConnection(sys_info.info.x11.display),
|
||||
(void *)(intptr_t)sys_info.info.x11.window, pixel_xres, pixel_yres);
|
||||
#endif
|
||||
break;
|
||||
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
|
||||
case SDL_SYSWM_WAYLAND:
|
||||
vulkan_->InitSurface(WINDOWSYSTEM_WAYLAND, (void*)sys_info.info.wl.display,
|
||||
(void *)sys_info.info.wl.surface, pixel_xres, pixel_yres);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(stderr, "Vulkan subsystem %d not supported\n", sys_info.subsystem);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!vulkan_->InitObjects()) {
|
||||
*error_message = vulkan_->InitError();
|
||||
Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
draw_ = Draw::T3DCreateVulkanContext(vulkan_, false);
|
||||
SetGPUBackend(GPUBackend::VULKAN);
|
||||
bool success = draw_->CreatePresets();
|
||||
assert(success);
|
||||
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SDLVulkanGraphicsContext::Shutdown() {
|
||||
if (draw_)
|
||||
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight());
|
||||
delete draw_;
|
||||
draw_ = nullptr;
|
||||
vulkan_->WaitUntilQueueIdle();
|
||||
vulkan_->DestroyObjects();
|
||||
vulkan_->DestroyDevice();
|
||||
vulkan_->DestroyDebugMsgCallback();
|
||||
vulkan_->DestroyInstance();
|
||||
delete vulkan_;
|
||||
vulkan_ = nullptr;
|
||||
finalize_glslang();
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
#include "SDL.h"
|
||||
#if !defined(__APPLE__)
|
||||
#include "SDL_syswm.h"
|
||||
#endif
|
||||
|
||||
#include "Common/GraphicsContext.h"
|
||||
#include "Common/Vulkan/VulkanContext.h"
|
||||
#include "Common/Vulkan/VulkanDebug.h"
|
||||
|
||||
#include "thin3d/thin3d.h"
|
||||
|
||||
class SDLVulkanGraphicsContext : public GraphicsContext {
|
||||
public:
|
||||
SDLVulkanGraphicsContext() {}
|
||||
~SDLVulkanGraphicsContext() {
|
||||
delete draw_;
|
||||
}
|
||||
|
||||
bool Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message);
|
||||
|
||||
void Shutdown() override;
|
||||
|
||||
void SwapBuffers() override {
|
||||
// We don't do it this way.
|
||||
}
|
||||
|
||||
void Resize() override {
|
||||
/*
|
||||
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight());
|
||||
vulkan_->DestroyObjects();
|
||||
// TODO: Take from real window dimensions
|
||||
int width = 1024;
|
||||
int height = 768;
|
||||
vulkan_->ReinitSurface(width, height);
|
||||
vulkan_->InitObjects();
|
||||
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight());
|
||||
*/
|
||||
}
|
||||
|
||||
void SwapInterval(int interval) override {
|
||||
}
|
||||
void *GetAPIContext() override {
|
||||
return vulkan_;
|
||||
}
|
||||
|
||||
Draw::DrawContext *GetDrawContext() override {
|
||||
return draw_;
|
||||
}
|
||||
private:
|
||||
Draw::DrawContext *draw_ = nullptr;
|
||||
VulkanContext *vulkan_ = nullptr;
|
||||
VulkanLogOptions g_LogOptions;
|
||||
};
|
||||
@@ -471,6 +471,9 @@ void SystemInfoScreen::CreateViews() {
|
||||
#else
|
||||
buildConfig->Add(new InfoItem("NDEBUG", ""));
|
||||
#endif
|
||||
#ifdef USE_ADDRESS_SANITIZER
|
||||
buildConfig->Add(new InfoItem("USE_ADDRESS_SANITIZER", ""));
|
||||
#endif
|
||||
#ifdef USING_GLES2
|
||||
buildConfig->Add(new InfoItem("USING_GLES2", ""));
|
||||
#endif
|
||||
|
||||
+5
-2
@@ -110,7 +110,7 @@ public:
|
||||
// this is sent from EMU thread! Make sure that Host handles it properly!
|
||||
virtual void BootDone() {
|
||||
g_symbolMap->SortSymbols();
|
||||
mainWindow->Boot();
|
||||
mainWindow->Notify(MainWindowMsg::BOOT_DONE);
|
||||
}
|
||||
|
||||
virtual bool IsDebuggingEnabled() {
|
||||
@@ -121,7 +121,10 @@ public:
|
||||
#endif
|
||||
}
|
||||
virtual bool AttemptLoadSymbolMap() {
|
||||
return g_symbolMap->LoadSymbolMap(SymbolMapFilename(PSP_CoreParameter().fileToStart));
|
||||
return false;
|
||||
// TODO: Make this work with Qt and threaded GL... not sure what's so broken.
|
||||
// auto fn = SymbolMapFilename(PSP_CoreParameter().fileToStart);
|
||||
// return g_symbolMap->LoadSymbolMap(fn);
|
||||
}
|
||||
virtual void PrepareShutdown() {
|
||||
g_symbolMap->SaveSymbolMap(SymbolMapFilename(PSP_CoreParameter().fileToStart));
|
||||
|
||||
@@ -140,6 +140,12 @@ void TextDrawerQt::ClearCache() {
|
||||
}
|
||||
cache_.clear();
|
||||
sizeCache_.clear();
|
||||
// Also wipe the font map.
|
||||
for (auto iter : fontMap_) {
|
||||
delete iter.second;
|
||||
}
|
||||
fontMap_.clear();
|
||||
fontHash_ = 0;
|
||||
}
|
||||
|
||||
void TextDrawerQt::DrawStringRect(DrawBuffer &target, const char *str, const Bounds &bounds, uint32_t color, int align) {
|
||||
|
||||
@@ -54,8 +54,11 @@ GLRenderManager::GLRenderManager() {
|
||||
|
||||
GLRenderManager::~GLRenderManager() {
|
||||
for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) {
|
||||
|
||||
_assert_(frameData_[i].deleter.IsEmpty());
|
||||
}
|
||||
// Was anything deleted during shutdown?
|
||||
deleter_.Perform();
|
||||
// _assert_(deleter_.IsEmpty());
|
||||
|
||||
if (!useThread_) {
|
||||
// The main thread is also the render thread.
|
||||
@@ -69,10 +72,29 @@ void GLRenderManager::ThreadStart() {
|
||||
}
|
||||
|
||||
void GLRenderManager::ThreadEnd() {
|
||||
ILOG("ThreadEnd");
|
||||
|
||||
// Wait for any shutdown to complete in StopThread().
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
queueRunner_.DestroyDeviceObjects();
|
||||
VLOG("PULL: Quitting");
|
||||
|
||||
// Good point to run all the deleters to get rid of leftover objects.
|
||||
for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) {
|
||||
frameData_[i].deleter.Perform();
|
||||
for (int j = 0; j < (int)frameData_[i].steps.size(); j++) {
|
||||
delete frameData_[i].steps[j];
|
||||
}
|
||||
frameData_[i].steps.clear();
|
||||
frameData_[i].initSteps.clear();
|
||||
}
|
||||
deleter_.Perform();
|
||||
|
||||
for (int i = 0; i < (int)steps_.size(); i++) {
|
||||
delete steps_[i];
|
||||
}
|
||||
steps_.clear();
|
||||
initSteps_.clear();
|
||||
}
|
||||
|
||||
bool GLRenderManager::ThreadFrame() {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <condition_variable>
|
||||
#include <cassert>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "gfx/gl_common.h"
|
||||
#include "math/dataconv.h"
|
||||
#include "Common/Log.h"
|
||||
@@ -152,9 +153,12 @@ class GLDeleter {
|
||||
public:
|
||||
void Perform();
|
||||
|
||||
bool IsEmpty() const {
|
||||
return shaders.empty() && programs.empty() && buffers.empty() && textures.empty() && inputLayouts.empty() && framebuffers.empty();
|
||||
}
|
||||
void Take(GLDeleter &other) {
|
||||
deleterMutex_.lock();
|
||||
_assert_msg_(G3D, shaders.empty() && programs.empty() && buffers.empty() && textures.empty() && inputLayouts.empty() && framebuffers.empty(), "Deleter already has stuff");
|
||||
_assert_msg_(G3D, IsEmpty(), "Deleter already has stuff");
|
||||
shaders = std::move(other.shaders);
|
||||
programs = std::move(other.programs);
|
||||
buffers = std::move(other.buffers);
|
||||
@@ -193,6 +197,9 @@ public:
|
||||
int semanticsMask_ = 0;
|
||||
};
|
||||
|
||||
// Note: The GLRenderManager is created and destroyed on the render thread, and the latter
|
||||
// happens after the emu thread has been destroyed. Therefore, it's safe to run wild deleting stuff
|
||||
// directly in the destructor.
|
||||
class GLRenderManager {
|
||||
public:
|
||||
GLRenderManager();
|
||||
@@ -701,7 +708,7 @@ private:
|
||||
// Swapchain.
|
||||
bool hasBegun = false;
|
||||
uint32_t curSwapchainImage = -1;
|
||||
|
||||
|
||||
GLDeleter deleter;
|
||||
std::set<GLPushBuffer *> activePushBuffers;
|
||||
};
|
||||
|
||||
@@ -297,6 +297,7 @@ public:
|
||||
OpenGLPipeline(GLRenderManager *render) : render_(render) {
|
||||
}
|
||||
~OpenGLPipeline() {
|
||||
ILOG("OpenGLPipeline released");
|
||||
for (auto &iter : shaders) {
|
||||
iter->Release();
|
||||
}
|
||||
@@ -477,7 +478,7 @@ private:
|
||||
OpenGLTexture *boundTextures_[8]{};
|
||||
int maxTextures_ = 0;
|
||||
DeviceCaps caps_{};
|
||||
|
||||
|
||||
// Bound state
|
||||
OpenGLPipeline *curPipeline_ = nullptr;
|
||||
OpenGLBuffer *curVBuffers_[4]{};
|
||||
@@ -519,7 +520,7 @@ OpenGLContext::OpenGLContext() {
|
||||
default:
|
||||
caps_.vendor = GPUVendor::VENDOR_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) {
|
||||
frameData_[i].push = new GLPushBuffer(&renderManager_, GL_ARRAY_BUFFER, 64 * 1024);
|
||||
renderManager_.RegisterPushBuffer(i, frameData_[i].push);
|
||||
|
||||
Reference in new issue
Block a user