mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
SDL: Allow running GL on thread.
Tested on a Mac.
This commit is contained in:
parent
0399088fc7
commit
59904c316b
1 changed files with 80 additions and 6 deletions
|
@ -14,9 +14,11 @@ SDLJoystick *joystick = NULL;
|
||||||
#include <bcm_host.h>
|
#include <bcm_host.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#include "base/display.h"
|
#include "base/display.h"
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
|
@ -32,6 +34,7 @@ SDLJoystick *joystick = NULL;
|
||||||
#include "util/text/utf8.h"
|
#include "util/text/utf8.h"
|
||||||
#include "util/text/parsers.h"
|
#include "util/text/parsers.h"
|
||||||
#include "math/math_util.h"
|
#include "math/math_util.h"
|
||||||
|
#include "thin3d/GLRenderManager.h"
|
||||||
#include "Common/Vulkan/VulkanContext.h"
|
#include "Common/Vulkan/VulkanContext.h"
|
||||||
#include "Common/Vulkan/VulkanDebug.h"
|
#include "Common/Vulkan/VulkanDebug.h"
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
|
@ -198,6 +201,8 @@ void EGL_Close() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
class GLRenderManager;
|
||||||
|
|
||||||
class SDLGLGraphicsContext : public DummyGraphicsContext {
|
class SDLGLGraphicsContext : public DummyGraphicsContext {
|
||||||
public:
|
public:
|
||||||
SDLGLGraphicsContext() {
|
SDLGLGraphicsContext() {
|
||||||
|
@ -218,21 +223,30 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwapBuffers() override {
|
void SwapBuffers() override {
|
||||||
#ifdef USING_EGL
|
renderManager_->Swap();
|
||||||
eglSwapBuffers(g_eglDisplay, g_eglSurface);
|
|
||||||
#else
|
|
||||||
SDL_GL_SwapWindow(window_);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Draw::DrawContext *GetDrawContext() override {
|
Draw::DrawContext *GetDrawContext() override {
|
||||||
return draw_;
|
return draw_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ThreadStart() override {
|
||||||
|
renderManager_->ThreadStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ThreadFrame() override {
|
||||||
|
return renderManager_->ThreadFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThreadEnd() override {
|
||||||
|
renderManager_->ThreadEnd();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Draw::DrawContext *draw_ = nullptr;
|
Draw::DrawContext *draw_ = nullptr;
|
||||||
SDL_Window *window_;
|
SDL_Window *window_;
|
||||||
SDL_GLContext glContext = nullptr;
|
SDL_GLContext glContext = nullptr;
|
||||||
|
GLRenderManager *renderManager_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns 0 on success.
|
// Returns 0 on success.
|
||||||
|
@ -340,9 +354,17 @@ int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std:
|
||||||
// Finally we can do the regular initialization.
|
// Finally we can do the regular initialization.
|
||||||
CheckGLExtensions();
|
CheckGLExtensions();
|
||||||
draw_ = Draw::T3DCreateGLContext();
|
draw_ = Draw::T3DCreateGLContext();
|
||||||
|
renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
||||||
SetGPUBackend(GPUBackend::OPENGL);
|
SetGPUBackend(GPUBackend::OPENGL);
|
||||||
bool success = draw_->CreatePresets();
|
bool success = draw_->CreatePresets();
|
||||||
assert(success);
|
assert(success);
|
||||||
|
renderManager_->SetSwapFunction([&]() {
|
||||||
|
#ifdef USING_EGL
|
||||||
|
eglSwapBuffers(g_eglDisplay, g_eglSurface);
|
||||||
|
#else
|
||||||
|
SDL_GL_SwapWindow(window_);
|
||||||
|
#endif
|
||||||
|
});
|
||||||
window_ = window;
|
window_ = window;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -691,6 +713,38 @@ void ToggleFullScreenIfFlagSet(SDL_Window *window) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class EmuThreadState {
|
||||||
|
DISABLED,
|
||||||
|
START_REQUESTED,
|
||||||
|
RUNNING,
|
||||||
|
QUIT_REQUESTED,
|
||||||
|
STOPPED,
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::thread emuThread;
|
||||||
|
static std::atomic<int> emuThreadState((int)EmuThreadState::DISABLED);
|
||||||
|
|
||||||
|
static void EmuThreadFunc() {
|
||||||
|
// There's no real requirement that NativeInit happen on this thread.
|
||||||
|
// We just call the update/render loop here.
|
||||||
|
emuThreadState = (int)EmuThreadState::RUNNING;
|
||||||
|
while (emuThreadState != (int)EmuThreadState::QUIT_REQUESTED) {
|
||||||
|
UpdateRunLoop();
|
||||||
|
}
|
||||||
|
emuThreadState = (int)EmuThreadState::STOPPED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EmuThreadStart() {
|
||||||
|
emuThreadState = (int)EmuThreadState::START_REQUESTED;
|
||||||
|
emuThread = std::thread(&EmuThreadFunc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EmuThreadStop() {
|
||||||
|
emuThreadState = (int)EmuThreadState::QUIT_REQUESTED;
|
||||||
|
emuThread.join();
|
||||||
|
emuThread = std::thread();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#undef main
|
#undef main
|
||||||
#endif
|
#endif
|
||||||
|
@ -888,6 +942,11 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Since we render from the main thread, there's nothing done here, but we call it to avoid confusion.
|
||||||
|
if (!graphicsContext->InitFromRenderThread(&error_message)) {
|
||||||
|
printf("Init from thread error: '%s'\n", error_message.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
SDL_SetWindowTitle(window, (app_name_nice + " " + PPSSPP_GIT_VERSION).c_str());
|
SDL_SetWindowTitle(window, (app_name_nice + " " + PPSSPP_GIT_VERSION).c_str());
|
||||||
|
|
||||||
#ifdef MOBILE_DEVICE
|
#ifdef MOBILE_DEVICE
|
||||||
|
@ -934,6 +993,9 @@ int main(int argc, char *argv[]) {
|
||||||
int framecount = 0;
|
int framecount = 0;
|
||||||
bool mouseDown = false;
|
bool mouseDown = false;
|
||||||
|
|
||||||
|
EmuThreadStart();
|
||||||
|
graphicsContext->ThreadStart();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
while (SDL_PollEvent(&event)) {
|
while (SDL_PollEvent(&event)) {
|
||||||
|
@ -1101,7 +1163,9 @@ int main(int argc, char *argv[]) {
|
||||||
if (g_QuitRequested)
|
if (g_QuitRequested)
|
||||||
break;
|
break;
|
||||||
const uint8_t *keys = SDL_GetKeyboardState(NULL);
|
const uint8_t *keys = SDL_GetKeyboardState(NULL);
|
||||||
UpdateRunLoop();
|
if (emuThreadState == (int)EmuThreadState::DISABLED) {
|
||||||
|
UpdateRunLoop();
|
||||||
|
}
|
||||||
if (g_QuitRequested)
|
if (g_QuitRequested)
|
||||||
break;
|
break;
|
||||||
#if !defined(MOBILE_DEVICE)
|
#if !defined(MOBILE_DEVICE)
|
||||||
|
@ -1118,12 +1182,22 @@ int main(int argc, char *argv[]) {
|
||||||
// glsl_refresh(); // auto-reloads modified GLSL shaders once per second.
|
// glsl_refresh(); // auto-reloads modified GLSL shaders once per second.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (emuThreadState != (int)EmuThreadState::DISABLED) {
|
||||||
|
if (!graphicsContext->ThreadFrame())
|
||||||
|
break;
|
||||||
|
}
|
||||||
graphicsContext->SwapBuffers();
|
graphicsContext->SwapBuffers();
|
||||||
|
|
||||||
ToggleFullScreenIfFlagSet(window);
|
ToggleFullScreenIfFlagSet(window);
|
||||||
time_update();
|
time_update();
|
||||||
framecount++;
|
framecount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
graphicsContext->ThreadEnd();
|
||||||
|
graphicsContext->ShutdownFromRenderThread();
|
||||||
|
|
||||||
|
EmuThreadStop();
|
||||||
|
|
||||||
delete joystick;
|
delete joystick;
|
||||||
NativeShutdownGraphics();
|
NativeShutdownGraphics();
|
||||||
graphicsContext->Shutdown();
|
graphicsContext->Shutdown();
|
||||||
|
|
Loading…
Add table
Reference in a new issue