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>
|
||||
#endif
|
||||
|
||||
#include <atomic>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <thread>
|
||||
|
||||
#include "base/display.h"
|
||||
#include "base/logging.h"
|
||||
|
@ -32,6 +34,7 @@ SDLJoystick *joystick = NULL;
|
|||
#include "util/text/utf8.h"
|
||||
#include "util/text/parsers.h"
|
||||
#include "math/math_util.h"
|
||||
#include "thin3d/GLRenderManager.h"
|
||||
#include "Common/Vulkan/VulkanContext.h"
|
||||
#include "Common/Vulkan/VulkanDebug.h"
|
||||
#include "math.h"
|
||||
|
@ -198,6 +201,8 @@ void EGL_Close() {
|
|||
}
|
||||
#endif
|
||||
|
||||
class GLRenderManager;
|
||||
|
||||
class SDLGLGraphicsContext : public DummyGraphicsContext {
|
||||
public:
|
||||
SDLGLGraphicsContext() {
|
||||
|
@ -218,21 +223,30 @@ public:
|
|||
}
|
||||
|
||||
void SwapBuffers() override {
|
||||
#ifdef USING_EGL
|
||||
eglSwapBuffers(g_eglDisplay, g_eglSurface);
|
||||
#else
|
||||
SDL_GL_SwapWindow(window_);
|
||||
#endif
|
||||
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.
|
||||
|
@ -340,9 +354,17 @@ int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std:
|
|||
// 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;
|
||||
}
|
||||
|
@ -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
|
||||
#undef main
|
||||
#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());
|
||||
|
||||
#ifdef MOBILE_DEVICE
|
||||
|
@ -934,6 +993,9 @@ int main(int argc, char *argv[]) {
|
|||
int framecount = 0;
|
||||
bool mouseDown = false;
|
||||
|
||||
EmuThreadStart();
|
||||
graphicsContext->ThreadStart();
|
||||
|
||||
while (true) {
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
|
@ -1101,7 +1163,9 @@ int main(int argc, char *argv[]) {
|
|||
if (g_QuitRequested)
|
||||
break;
|
||||
const uint8_t *keys = SDL_GetKeyboardState(NULL);
|
||||
UpdateRunLoop();
|
||||
if (emuThreadState == (int)EmuThreadState::DISABLED) {
|
||||
UpdateRunLoop();
|
||||
}
|
||||
if (g_QuitRequested)
|
||||
break;
|
||||
#if !defined(MOBILE_DEVICE)
|
||||
|
@ -1118,12 +1182,22 @@ int main(int argc, char *argv[]) {
|
|||
// glsl_refresh(); // auto-reloads modified GLSL shaders once per second.
|
||||
}
|
||||
|
||||
if (emuThreadState != (int)EmuThreadState::DISABLED) {
|
||||
if (!graphicsContext->ThreadFrame())
|
||||
break;
|
||||
}
|
||||
graphicsContext->SwapBuffers();
|
||||
|
||||
ToggleFullScreenIfFlagSet(window);
|
||||
time_update();
|
||||
framecount++;
|
||||
}
|
||||
|
||||
graphicsContext->ThreadEnd();
|
||||
graphicsContext->ShutdownFromRenderThread();
|
||||
|
||||
EmuThreadStop();
|
||||
|
||||
delete joystick;
|
||||
NativeShutdownGraphics();
|
||||
graphicsContext->Shutdown();
|
||||
|
|
Loading…
Add table
Reference in a new issue