Skip to content

Commit

Permalink
Libretro port.
Browse files Browse the repository at this point in the history
  • Loading branch information
aliaspider committed Mar 24, 2018
1 parent 686717e commit c4f7790
Show file tree
Hide file tree
Showing 22 changed files with 5,674 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .travis.sh
Expand Up @@ -106,6 +106,8 @@ travis_script() {

if [ "$QT" = "TRUE" ]; then
./b.sh --qt
elif [ "$LIBRETRO" = "TRUE" ]; then
./b.sh --libretro
else
./b.sh --headless
fi
Expand Down
8 changes: 8 additions & 0 deletions .travis.yml
Expand Up @@ -64,6 +64,14 @@ matrix:
compiler: "gcc"
env: PPSSPP_BUILD_TYPE=Linux
QT=TRUE
- os: linux
compiler: "gcc"
env: PPSSPP_BUILD_TYPE=Linux
LIBRETRO=TRUE
- os: linux
compiler: "clang"
env: PPSSPP_BUILD_TYPE=Linux
LIBRETRO=TRUE
- os: osx
osx_image: xcode8
compiler: "clang macos"
Expand Down
13 changes: 13 additions & 0 deletions CMakeLists.txt
Expand Up @@ -115,6 +115,7 @@ option(MOBILE_DEVICE "Set to ON when targeting a mobile device" ${MOBILE_DEVICE}
option(HEADLESS "Set to OFF to not generate the PPSSPPHeadless target" ${HEADLESS})
option(UNITTEST "Set to ON to generate the unittest target" ${UNITTEST})
option(SIMULATOR "Set to ON when targeting an x86 simulator of an ARM platform" ${SIMULATOR})
option(LIBRETRO "Set to ON to generate the libretro target" OFF)
# :: Options
option(USE_FFMPEG "Build with FFMPEG support" ${USE_FFMPEG})
option(USE_SYSTEM_FFMPEG "Dynamically link against system FFMPEG" ${USE_SYSTEM_FFMPEG})
Expand All @@ -135,6 +136,14 @@ if(UNIX AND NOT (APPLE OR ANDROID) AND VULKAN)
endif()
endif()

if(LIBRETRO)
add_definitions(-D__LIBRETRO__)
add_definitions(-DGLEW_NO_GLU)
if(NOT MSVC)
add_compile_options(-fPIC)
endif()
endif()

if(ANDROID)
set(CoreLibName ppsspp_jni)
set(CoreLinkType SHARED)
Expand Down Expand Up @@ -1884,6 +1893,10 @@ if(UNITTEST)
setup_target_project(unitTest unittest)
endif()

if(LIBRETRO)
add_subdirectory(libretro)
endif()

if (TargetBin)
if (IOS OR APPLE)
if (APPLE AND NOT IOS)
Expand Down
3 changes: 3 additions & 0 deletions b.sh
Expand Up @@ -37,6 +37,9 @@ do
--headless) echo "Headless mode enabled"
CMAKE_ARGS="-DHEADLESS=ON ${CMAKE_ARGS}"
;;
--libretro) echo "Build Libretro core"
CMAKE_ARGS="-DLIBRETRO=ON ${CMAKE_ARGS}"
;;
--unittest) echo "Build unittest"
CMAKE_ARGS="-DUNITTEST=ON ${CMAKE_ARGS}"
;;
Expand Down
4 changes: 4 additions & 0 deletions libretro/.gitignore
@@ -0,0 +1,4 @@
*.bc
*.so
*.dll
*.dylib
21 changes: 21 additions & 0 deletions libretro/CMakeLists.txt
@@ -0,0 +1,21 @@
set(LIBRETRO_SRCS
libretro.cpp
LibretroGraphicsContext.cpp
LibretroGLContext.cpp
LibretroVulkanContext.cpp
libretro_vulkan.cpp
)

include_directories(libretro)

add_library(ppsspp_libretro SHARED ${LIBRETRO_SRCS})
set(LIBRARY_OUTPUT_PATH "${CMAKE_BINARY_DIR}")
set_target_properties(ppsspp_libretro PROPERTIES PREFIX "")
if(ANDROID)
set_target_properties(ppsspp_libretro PROPERTIES SUFFIX "_android.so")
endif()

if(NOT MSVC)
target_link_libraries(ppsspp_libretro "-Wl,-Bsymbolic")
endif()
target_link_libraries(ppsspp_libretro ${LinkCommon})
51 changes: 51 additions & 0 deletions libretro/LibretroGLContext.cpp
@@ -0,0 +1,51 @@

#include "Common/Log.h"
#include "Core/Config.h"
#include "Core/System.h"
#include "gfx_es2/gpu_features.h"

#include "libretro/LibretroGLContext.h"

bool LibretroGLContext::Init()
{
if (!LibretroHWRenderContext::Init())
return false;

libretro_get_proc_address = hw_render_.get_proc_address;

g_Config.iGPUBackend = (int)GPUBackend::OPENGL;
return true;
}

void LibretroGLContext::Shutdown()
{
LibretroGraphicsContext::Shutdown();
libretro_get_proc_address = nullptr;
#if 0
NativeShutdownGraphics();
finalize_glslang();
#endif
}

void LibretroGLContext::CreateDrawContext()
{
if (!glewInitDone)
{
#if !defined(IOS) && !defined(USING_GLES2)
if (glewInit() != GLEW_OK)
{
ERROR_LOG(G3D, "glewInit() failed.\n");
return;
}
#endif
glewInitDone = true;
CheckGLExtensions();
}
draw_ = Draw::T3DCreateGLContext();
renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
}
void LibretroGLContext::DestroyDrawContext()
{
LibretroHWRenderContext::DestroyDrawContext();
renderManager_ = nullptr;
}
47 changes: 47 additions & 0 deletions libretro/LibretroGLContext.h
@@ -0,0 +1,47 @@
#pragma once

#include "gfx/gl_common.h"
#include "libretro/LibretroGraphicsContext.h"
#include "thin3d/GLRenderManager.h"

class LibretroGLContext : public LibretroHWRenderContext {
public:
LibretroGLContext()
:
#ifdef USING_GLES2
HWRenderContext(RETRO_HW_CONTEXT_OPENGLES2)
#elif defined(HAVE_OPENGL_CORE)
HWRenderContext(RETRO_HW_CONTEXT_OPENGL_CORE, 3, 1)
#else
LibretroHWRenderContext(RETRO_HW_CONTEXT_OPENGL)
#endif
{
hw_render_.bottom_left_origin = true;
}

bool Init() override;
void Shutdown() override;
void CreateDrawContext() override;
void DestroyDrawContext() override;
void SetRenderTarget() override
{
extern GLuint g_defaultFBO;
g_defaultFBO = hw_render_.get_current_framebuffer();
}

void ThreadStart() override { renderManager_->ThreadStart(); }
bool ThreadFrame() override { return renderManager_->ThreadFrame(); }
void ThreadEnd() override { renderManager_->ThreadEnd(); }
void StopThread() override
{
renderManager_->WaitUntilQueueIdle();
renderManager_->StopThread();
}

GPUCore GetGPUCore() override { return GPUCORE_GLES; }
const char *Ident() override { return "OpenGL"; }

private:
GLRenderManager *renderManager_ = nullptr;
bool glewInitDone = false;
};
116 changes: 116 additions & 0 deletions libretro/LibretroGraphicsContext.cpp
@@ -0,0 +1,116 @@

#include "libretro/libretro.h"
#include "libretro/LibretroGraphicsContext.h"
#include "libretro/LibretroGLContext.h"
#ifndef NO_VULKAN
#include "libretro/LibretroVulkanContext.h"
#endif

#include "Common/Log.h"
#include "Core/Config.h"
#include "Core/System.h"
#include "GPU/GPUInterface.h"

retro_video_refresh_t LibretroGraphicsContext::video_cb;
retro_hw_get_proc_address_t libretro_get_proc_address;

void retro_set_video_refresh(retro_video_refresh_t cb) { LibretroGraphicsContext::video_cb = cb; }
static void context_reset() { ((LibretroHWRenderContext *)Libretro::ctx)->ContextReset(); }
static void context_destroy() { ((LibretroHWRenderContext *)Libretro::ctx)->ContextDestroy(); }

bool LibretroHWRenderContext::Init() { return Libretro::environ_cb(RETRO_ENVIRONMENT_SET_HW_RENDER, &hw_render_); }

LibretroHWRenderContext::LibretroHWRenderContext(retro_hw_context_type context_type, unsigned version_major, unsigned version_minor)
{
hw_render_.context_type = context_type;
hw_render_.version_major = version_major;
hw_render_.version_minor = version_minor;
hw_render_.context_reset = context_reset;
hw_render_.context_destroy = context_destroy;
hw_render_.depth = true;
}

void LibretroHWRenderContext::ContextReset()
{
INFO_LOG(G3D, "Context reset");

// needed to restart the thread
// TODO: find a way to move this to ContextDestroy.
if (Libretro::useEmuThread && draw_ && Libretro::emuThreadState != Libretro::EmuThreadState::PAUSED)
DestroyDrawContext();

if (!draw_)
{
CreateDrawContext();
PSP_CoreParameter().thin3d = draw_;
draw_->CreatePresets();
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight);
}

if (gpu)
gpu->DeviceRestore();
}

void LibretroHWRenderContext::ContextDestroy()
{
INFO_LOG(G3D, "Context destroy");

if (Libretro::useEmuThread)
{
#if 0
Libretro::EmuThreadPause();
#else
Libretro::EmuThreadStop();
#endif
}

gpu->DeviceLost();
}

LibretroGraphicsContext *LibretroGraphicsContext::CreateGraphicsContext()
{
LibretroGraphicsContext *ctx;

ctx = new LibretroGLContext();

if (ctx->Init())
return ctx;

delete ctx;

#ifndef NO_VULKAN
ctx = new LibretroVulkanContext();

if (ctx->Init())
return ctx;

delete ctx;
#endif

#ifdef _WIN32
ctx = new LibretroD3D11Context();

if (ctx->Init())
return ctx;

delete ctx;

ctx = new LibretroD3D9Context();

if (ctx->Init())
return ctx;

delete ctx;
#endif

#if 1
ctx = new LibretroSoftwareContext();

if (ctx->Init())
return ctx;

delete ctx;
#endif

return new LibretroNullContext();
}

0 comments on commit c4f7790

Please sign in to comment.