Core: Improve OpenGL integration, update Qt to use improvements

This commit is contained in:
Vicki Pfau 2019-05-14 13:02:36 -07:00
parent 49a9da3e5c
commit 8450417086
17 changed files with 228 additions and 80 deletions

View File

@ -57,7 +57,7 @@ if(NOT LIBMGBA_ONLY)
set(BUILD_SHARED ON CACHE BOOL "Build a shared library")
set(SKIP_LIBRARY OFF CACHE BOOL "Skip building the library (useful for only building libretro or OpenEmu cores)")
set(BUILD_GL ON CACHE BOOL "Build with OpenGL")
set(BUILD_GLES2 OFF CACHE BOOL "Build with OpenGL|ES 2")
set(BUILD_GLES2 ON CACHE BOOL "Build with OpenGL|ES 2")
set(BUILD_GLES3 OFF CACHE BOOL "Build with OpenGL|ES 3")
set(USE_EPOXY ON CACHE STRING "Build with libepoxy")
set(DISABLE_DEPS OFF CACHE BOOL "Build without dependencies")
@ -447,7 +447,7 @@ set(FEATURE_DEFINES)
set(FEATURE_FLAGS)
set(FEATURES)
set(ENABLES)
if(CMAKE_SYSTEM_NAME MATCHES .*BSD)
if(CMAKE_SYSTEM_NAME MATCHES ".*BSD|DragonFly")
set(LIBEDIT_LIBRARIES -ledit)
if (CMAKE_SYSTEM_NAME STREQUAL OpenBSD)
list(APPEND LIBEDIT_LIBRARIES -ltermcap)
@ -462,9 +462,9 @@ if(BUILD_GL)
endif()
endif()
if(NOT BUILD_GL)
set(OPENGLE_LIBRARY "" CACHE PATH "" FORCE)
set(OPENGL_LIBRARY "" CACHE PATH "" FORCE)
endif()
if(BUILD_GLES2 AND NOT BUILD_RASPI)
if(BUILD_GLES2 AND NOT BUILD_RASPI AND NOT CMAKE_SYSTEM_NAME MATCHES "^(Windows|Darwin|Linux|.*BSD|DragonFly|Haiku)$")
find_path(OPENGLES2_INCLUDE_DIR NAMES GLES2/gl2.h)
find_library(OPENGLES2_LIBRARY NAMES GLESv2 GLESv2_CM)
if(NOT OPENGLES2_INCLUDE_DIR OR NOT OPENGLES2_LIBRARY)
@ -474,6 +474,16 @@ endif()
if(NOT BUILD_GLES2)
set(OPENGLES2_LIBRARY "" CACHE PATH "" FORCE)
endif()
if(BUILD_GL)
list(APPEND OS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/opengl/gl.c)
list(APPEND OS_LIB ${OPENGL_LIBRARY})
include_directories(${OPENGL_INCLUDE_DIR})
endif()
if(BUILD_GLES2)
list(APPEND OS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/opengl/gles2.c)
list(APPEND OS_LIB ${OPENGLES2_LIBRARY})
include_directories(${OPENGLES2_INCLUDE_DIR})
endif()
if(BUILD_GLES3)
find_path(OPENGLES3_INCLUDE_DIR NAMES GLES3/gl3.h)
find_library(OPENGLES3_LIBRARY NAMES GLESv3 GLESv2)
@ -733,6 +743,10 @@ if(USE_EPOXY)
link_directories(${EPOXY_LIBRARY_DIRS})
set(OPENGLES2_LIBRARY ${EPOXY_LIBRARIES})
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libepoxy0")
elseif(BUILD_GL)
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libgl1|libgles2")
elseif(BUILD_GLES2)
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libgles2")
endif()
if(USE_SQLITE3)

View File

@ -64,6 +64,7 @@ struct mCore {
void (*deinit)(struct mCore*);
enum mPlatform (*platform)(const struct mCore*);
bool (*supportsFeature)(const struct mCore*, enum mCoreFeature);
void (*setSync)(struct mCore*, struct mCoreSync*);
void (*loadConfig)(struct mCore*, const struct mCoreConfig*);

View File

@ -80,6 +80,10 @@ enum mColorFormat {
mCOLOR_ANY = -1
};
enum mCoreFeature {
mCORE_FEATURE_OPENGL = 1,
};
struct mCoreCallbacks {
void* context;
void (*videoFrameStarted)(void* context);

View File

@ -16,6 +16,8 @@ CXX_GUARD_START
#include <mgba/internal/gba/renderers/common.h>
#include <mgba/internal/gba/video.h>
#if defined(BUILD_GLES2) || defined(BUILD_GLES3)
#ifdef USE_EPOXY
#include <epoxy/gl.h>
#elif defined(BUILD_GL)
@ -27,7 +29,7 @@ CXX_GUARD_START
#include <GL/glext.h>
#endif
#else
#include <GLES2/gl2.h>
#include <GLES3/gl3.h>
#endif
struct GBAVideoGLAffine {
@ -137,6 +139,9 @@ struct GBAVideoGLRenderer {
GLuint outputTex;
#ifdef BUILD_GLES3
uint16_t shadowPalette[512];
#endif
GLuint paletteTex;
bool paletteDirty;
@ -182,6 +187,8 @@ struct GBAVideoGLRenderer {
void GBAVideoGLRendererCreate(struct GBAVideoGLRenderer* renderer);
#endif
CXX_GUARD_END
#endif

View File

@ -138,6 +138,14 @@ static enum mPlatform _GBCorePlatform(const struct mCore* core) {
return PLATFORM_GB;
}
static bool _GBCoreSupportsFeature(const struct mCore* core, enum mCoreFeature feature) {
UNUSED(core);
switch (feature) {
default:
return false;
}
}
static void _GBCoreSetSync(struct mCore* core, struct mCoreSync* sync) {
struct GB* gb = core->board;
gb->sync = sync;
@ -888,6 +896,7 @@ struct mCore* GBCoreCreate(void) {
core->init = _GBCoreInit;
core->deinit = _GBCoreDeinit;
core->platform = _GBCorePlatform;
core->supportsFeature = _GBCoreSupportsFeature;
core->setSync = _GBCoreSetSync;
core->loadConfig = _GBCoreLoadConfig;
core->desiredVideoDimensions = _GBCoreDesiredVideoDimensions;

View File

@ -17,7 +17,9 @@
#ifndef DISABLE_THREADING
#include <mgba/feature/thread-proxy.h>
#endif
#ifdef BUILD_GLES2
#include <mgba/internal/gba/renderers/gl.h>
#endif
#include <mgba/internal/gba/renderers/proxy.h>
#include <mgba/internal/gba/renderers/video-software.h>
#include <mgba/internal/gba/savedata.h>
@ -124,7 +126,9 @@ struct mVideoLogContext;
struct GBACore {
struct mCore d;
struct GBAVideoSoftwareRenderer renderer;
#ifdef BUILD_GLES2
struct GBAVideoGLRenderer glRenderer;
#endif
struct GBAVideoProxyRenderer proxyRenderer;
struct mVideoLogContext* logContext;
struct mCoreCallbacks logCallbacks;
@ -170,8 +174,10 @@ static bool _GBACoreInit(struct mCore* core) {
GBAVideoSoftwareRendererCreate(&gbacore->renderer);
gbacore->renderer.outputBuffer = NULL;
#ifdef BUILD_GLES2
GBAVideoGLRendererCreate(&gbacore->glRenderer);
gbacore->glRenderer.outputTex = -1;
#endif
#ifndef DISABLE_THREADING
mVideoThreadProxyCreate(&gbacore->threadProxy);
@ -212,6 +218,20 @@ static enum mPlatform _GBACorePlatform(const struct mCore* core) {
return PLATFORM_GBA;
}
static bool _GBACoreSupportsFeature(const struct mCore* core, enum mCoreFeature feature) {
UNUSED(core);
switch (feature) {
case mCORE_FEATURE_OPENGL:
#ifdef BUILD_GLES2
return true;
#else
return false;
#endif
default:
return false;
}
}
static void _GBACoreSetSync(struct mCore* core, struct mCoreSync* sync) {
struct GBA* gba = core->board;
gba->sync = sync;
@ -261,9 +281,12 @@ static void _GBACoreLoadConfig(struct mCore* core, const struct mCoreConfig* con
}
static void _GBACoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) {
#ifdef BUILD_GLES2
struct GBACore* gbacore = (struct GBACore*) core;
int fakeBool;
int scale = gbacore->glRenderer.scale;
#else
int scale = 1;
#endif
*width = GBA_VIDEO_HORIZONTAL_PIXELS * scale;
*height = GBA_VIDEO_VERTICAL_PIXELS * scale;
@ -277,8 +300,13 @@ static void _GBACoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t s
}
static void _GBACoreSetVideoGLTex(struct mCore* core, unsigned texid) {
#ifdef BUILD_GLES2
struct GBACore* gbacore = (struct GBACore*) core;
gbacore->glRenderer.outputTex = texid;
#else
UNUSED(core);
UNUSED(texid);
#endif
}
static void _GBACoreGetPixels(struct mCore* core, const void** buffer, size_t* stride) {
@ -403,16 +431,22 @@ static void _GBACoreChecksum(const struct mCore* core, void* data, enum mCoreChe
static void _GBACoreReset(struct mCore* core) {
struct GBACore* gbacore = (struct GBACore*) core;
struct GBA* gba = (struct GBA*) core->board;
if (gbacore->renderer.outputBuffer || gbacore->glRenderer.outputTex != (unsigned) -1) {
if (gbacore->renderer.outputBuffer
#ifdef BUILD_GLES2
|| gbacore->glRenderer.outputTex != (unsigned) -1
#endif
) {
struct GBAVideoRenderer* renderer;
if (gbacore->renderer.outputBuffer) {
renderer = &gbacore->renderer.d;
}
int fakeBool;
#ifdef BUILD_GLES2
if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) {
renderer = &gbacore->glRenderer.d;
mCoreConfigGetIntValue(&core->config, "videoScale", &gbacore->glRenderer.scale);
}
#endif
#ifndef DISABLE_THREADING
if (mCoreConfigGetIntValue(&core->config, "threadedVideo", &fakeBool) && fakeBool) {
if (!core->videoLogger) {
@ -952,6 +986,7 @@ struct mCore* GBACoreCreate(void) {
core->init = _GBACoreInit;
core->deinit = _GBACoreDeinit;
core->platform = _GBACorePlatform;
core->supportsFeature = _GBACoreSupportsFeature;
core->setSync = _GBACoreSetSync;
core->loadConfig = _GBACoreLoadConfig;
core->desiredVideoDimensions = _GBACoreDesiredVideoDimensions;

View File

@ -5,6 +5,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <mgba/internal/gba/renderers/gl.h>
#if defined(BUILD_GLES2) || defined(BUILD_GLES3)
#include <mgba/core/cache-set.h>
#include <mgba/internal/arm/macros.h>
#include <mgba/internal/gba/io.h>
@ -90,7 +92,7 @@ static const char* const _renderTile256 =
" return color;\n"
"}";
const static struct GBAVideoGLUniform _uniformsMode0[] = {
static const struct GBAVideoGLUniform _uniformsMode0[] = {
{ "loc", GBA_GL_VS_LOC, },
{ "maxPos", GBA_GL_VS_MAXPOS, },
{ "vram", GBA_GL_BG_VRAM, },
@ -155,7 +157,7 @@ static const char* const _fetchTileNoOverflow =
" return renderTile(coord);\n"
"}";
const static struct GBAVideoGLUniform _uniformsMode2[] = {
static const struct GBAVideoGLUniform _uniformsMode2[] = {
{ "loc", GBA_GL_VS_LOC, },
{ "maxPos", GBA_GL_VS_MAXPOS, },
{ "vram", GBA_GL_BG_VRAM, },
@ -221,7 +223,7 @@ static const char* const _renderMode2 =
" flags = inflags / flagCoeff;\n"
"}";
const static struct GBAVideoGLUniform _uniformsObj[] = {
static const struct GBAVideoGLUniform _uniformsObj[] = {
{ "loc", GBA_GL_VS_LOC, },
{ "maxPos", GBA_GL_VS_MAXPOS, },
{ "vram", GBA_GL_OBJ_VRAM, },
@ -268,7 +270,7 @@ static const char* const _renderObj =
" window = objwin.yz;\n"
"}";
const static struct GBAVideoGLUniform _uniformsComposite[] = {
static const struct GBAVideoGLUniform _uniformsComposite[] = {
{ "loc", GBA_GL_VS_LOC, },
{ "maxPos", GBA_GL_VS_MAXPOS, },
{ "scale", GBA_GL_COMPOSITE_SCALE, },
@ -329,7 +331,7 @@ static const char* const _composite =
" }\n"
"}";
const static struct GBAVideoGLUniform _uniformsFinalize[] = {
static const struct GBAVideoGLUniform _uniformsFinalize[] = {
{ "loc", GBA_GL_VS_LOC, },
{ "maxPos", GBA_GL_VS_MAXPOS, },
{ "scale", GBA_GL_FINALIZE_SCALE, },
@ -413,8 +415,10 @@ void _compileShader(struct GBAVideoGLRenderer* glRenderer, GLuint program, const
mLOG(GBA_VIDEO, ERROR, "Program link failure: %s", log);
}
glDeleteShader(fs);
#ifndef BUILD_GLES3
glBindFragDataLocation(program, 0, "color");
glBindFragDataLocation(program, 1, "flags");
#endif
}
static void _initFramebufferTexture(GLuint tex, GLenum format, GLenum attachment, int scale) {
@ -550,18 +554,24 @@ void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer) {
shaderBuffer[2] = _renderTile16;
_compileShader(glRenderer, glRenderer->objProgram[0], shaderBuffer, 3, vs, log);
_lookupUniforms(glRenderer->objProgram[0], glRenderer->objUniforms[0], _uniformsObj);
#ifndef BUILD_GLES3
glBindFragDataLocation(glRenderer->objProgram[0], 2, "window");
#endif
shaderBuffer[2] = _renderTile256;
_compileShader(glRenderer, glRenderer->objProgram[1], shaderBuffer, 3, vs, log);
_lookupUniforms(glRenderer->objProgram[1], glRenderer->objUniforms[1], _uniformsObj);
#ifndef BUILD_GLES3
glBindFragDataLocation(glRenderer->objProgram[1], 2, "window");
#endif
shaderBuffer[1] = _composite;
_compileShader(glRenderer, glRenderer->compositeProgram, shaderBuffer, 2, vs, log);
_lookupUniforms(glRenderer->compositeProgram, glRenderer->compositeUniforms, _uniformsComposite);
#ifndef BUILD_GLES3
glBindFragDataLocation(glRenderer->compositeProgram, 2, "oldColor");
glBindFragDataLocation(glRenderer->compositeProgram, 3, "oldFlags");
#endif
shaderBuffer[1] = _finalize;
_compileShader(glRenderer, glRenderer->finalizeProgram, shaderBuffer, 2, vs, log);
@ -585,7 +595,6 @@ void GBAVideoGLRendererDeinit(struct GBAVideoRenderer* renderer) {
glDeleteProgram(glRenderer->bgProgram[3]);
glDeleteProgram(glRenderer->bgProgram[4]);
glDeleteProgram(glRenderer->bgProgram[5]);
glDeleteProgram(glRenderer->bgProgram[6]);
glDeleteProgram(glRenderer->objProgram[0]);
glDeleteProgram(glRenderer->objProgram[1]);
glDeleteProgram(glRenderer->compositeProgram);
@ -611,9 +620,13 @@ void GBAVideoGLRendererWriteOAM(struct GBAVideoRenderer* renderer, uint32_t oam)
}
void GBAVideoGLRendererWritePalette(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value) {
struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer;
#ifdef BUILD_GLES3
glRenderer->shadowPalette[address >> 1] = (value & 0x3F) | ((value & 0x7FE0) << 1);
#else
UNUSED(address);
UNUSED(value);
struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer;
#endif
glRenderer->paletteDirty = true;
}
@ -822,7 +835,11 @@ void GBAVideoGLRendererDrawScanline(struct GBAVideoRenderer* renderer, int y) {
struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer;
if (glRenderer->paletteDirty) {
glBindTexture(GL_TEXTURE_2D, glRenderer->paletteTex);
#ifdef BUILD_GLES3
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, 16, 32, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_6_5, glRenderer->shadowPalette);
#else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5_A1, 16, 32, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, glRenderer->d.palette);
#endif
glRenderer->paletteDirty = false;
}
int i;
@ -841,33 +858,33 @@ void GBAVideoGLRendererDrawScanline(struct GBAVideoRenderer* renderer, int y) {
glBindFramebuffer(GL_FRAMEBUFFER, glRenderer->fbo[GBA_GL_FBO_COMPOSITE]);
glEnable(GL_SCISSOR_TEST);
glScissor(0, y * glRenderer->scale, GBA_VIDEO_HORIZONTAL_PIXELS * glRenderer->scale, glRenderer->scale);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT0 });
glClear(GL_COLOR_BUFFER_BIT);
if (y == 0) {
glDisable(GL_SCISSOR_TEST);
glDrawBuffer(GL_COLOR_ATTACHMENT1);
glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT1 });
glClearColor(1, (glRenderer->target1Bd | (glRenderer->target2Bd * 2) | (glRenderer->blendEffect * 4)) / 32.f,
(glRenderer->blendEffect == BLEND_ALPHA ? glRenderer->blda : glRenderer->bldy) / 16.f, glRenderer->bldb / 16.f);
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0, 0, 0, 0);
glDrawBuffer(GL_COLOR_ATTACHMENT3);
glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT3 });
glClear(GL_COLOR_BUFFER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, glRenderer->fbo[GBA_GL_FBO_OBJ]);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT0 });
glClear(GL_COLOR_BUFFER_BIT);
glDrawBuffer(GL_COLOR_ATTACHMENT1);
glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT1 });
glClear(GL_COLOR_BUFFER_BIT);
for (i = 0; i < 4; ++i) {
glBindFramebuffer(GL_FRAMEBUFFER, glRenderer->bg[i].fbo);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT0 });
glClear(GL_COLOR_BUFFER_BIT);
glDrawBuffer(GL_COLOR_ATTACHMENT1);
glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT1 });
glClear(GL_COLOR_BUFFER_BIT);
}
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT0 });
glEnable(GL_SCISSOR_TEST);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
@ -1310,3 +1327,5 @@ void GBAVideoGLRendererDrawWindow(struct GBAVideoGLRenderer* renderer, int y) {
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
#endif

View File

@ -47,17 +47,6 @@ if(APPLE)
endif()
endif()
if(BUILD_GL)
list(APPEND PLATFORM_SRC ${CMAKE_SOURCE_DIR}/src/platform/opengl/gl.c)
if(NOT WIN32 OR USE_EPOXY)
list(APPEND PLATFORM_SRC ${CMAKE_SOURCE_DIR}/src/platform/opengl/gles2.c)
endif()
endif()
if(BUILD_GLES2)
list(APPEND PLATFORM_SRC ${CMAKE_SOURCE_DIR}/src/platform/opengl/gles2.c)
endif()
get_target_property(QT_TYPE Qt5::Core TYPE)
if(QT_TYPE STREQUAL STATIC_LIBRARY)
set(QT_STATIC ON)
@ -245,7 +234,7 @@ if(NOT DEFINED DATADIR)
set(DATADIR ${CMAKE_INSTALL_DATADIR}/${BINARY_NAME})
endif()
endif()
if(BUILD_GL OR BUILD_GLES2)
if(BUILD_GL OR BUILD_GLES2 OR BUILD_EPOXY)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/res/shaders DESTINATION ${DATADIR} COMPONENT ${BINARY_NAME}-qt)
endif()
install(FILES ${CMAKE_SOURCE_DIR}/res/nointro.dat DESTINATION ${DATADIR} COMPONENT ${BINARY_NAME}-qt)
@ -291,7 +280,7 @@ add_executable(${BINARY_NAME}-qt WIN32 MACOSX_BUNDLE main.cpp ${CMAKE_SOURCE_DIR
set_target_properties(${BINARY_NAME}-qt PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/res/info.plist.in COMPILE_DEFINITIONS "${FEATURE_DEFINES};${FUNCTION_DEFINES};${OS_DEFINES};${QT_DEFINES}" COMPILE_OPTIONS "${FEATURE_FLAGS}")
list(APPEND QT_LIBRARIES Qt5::Widgets)
if(BUILD_GL OR BUILD_GLES2)
if(BUILD_GL OR BUILD_GLES2 OR BUILD_EPOXY)
list(APPEND QT_LIBRARIES Qt5::OpenGL ${OPENGL_LIBRARY} ${OPENGLES2_LIBRARY})
endif()
if(QT_STATIC)

View File

@ -40,16 +40,6 @@ CoreController::CoreController(mCore* core, QObject* parent)
m_threadContext.core = core;
m_threadContext.userData = this;
QSize size(1024, 2048);
m_buffers[0].resize(size.width() * size.height() * sizeof(color_t));
m_buffers[1].resize(size.width() * size.height() * sizeof(color_t));
m_buffers[0].fill(0xFF);
m_buffers[1].fill(0xFF);
m_activeBuffer = &m_buffers[0];
m_completeBuffer = m_buffers[0];
m_threadContext.core->setVideoBuffer(m_threadContext.core, reinterpret_cast<color_t*>(m_activeBuffer->data()), size.width());
m_resetActions.append([this]() {
if (m_autoload) {
mCoreLoadState(m_threadContext.core, 0, m_loadStateFlags);
@ -91,8 +81,10 @@ CoreController::CoreController(mCore* core, QObject* parent)
controller->m_resetActions.clear();
if (!controller->m_hwaccel) {
controller->m_activeBuffer = &controller->m_buffers[0];
context->core->setVideoBuffer(context->core, reinterpret_cast<color_t*>(controller->m_activeBuffer->data()), controller->screenDimensions().width());
}
controller->finishFrame();
};
@ -211,6 +203,9 @@ CoreController::~CoreController() {
const color_t* CoreController::drawContext() {
QMutexLocker locker(&m_mutex);
if (m_hwaccel) {
return nullptr;
}
return reinterpret_cast<const color_t*>(m_completeBuffer.constData());
}
@ -340,6 +335,18 @@ void CoreController::setLogger(LogController* logger) {
}
void CoreController::start() {
if (!m_hwaccel) {
QSize size(1024, 2048);
m_buffers[0].resize(size.width() * size.height() * sizeof(color_t));
m_buffers[1].resize(size.width() * size.height() * sizeof(color_t));
m_buffers[0].fill(0xFF);
m_buffers[1].fill(0xFF);
m_activeBuffer = &m_buffers[0];
m_completeBuffer = m_buffers[0];
m_threadContext.core->setVideoBuffer(m_threadContext.core, reinterpret_cast<color_t*>(m_activeBuffer->data()), size.width());
}
if (!m_patched) {
mCoreAutoloadPatch(m_threadContext.core);
}
@ -800,6 +807,16 @@ void CoreController::endVideoLog() {
m_vl = nullptr;
}
void CoreController::setFramebufferHandle(int fb) {
Interrupter interrupter(this);
if (fb < 0) {
m_hwaccel = false;
} else {
m_threadContext.core->setVideoGLTex(m_threadContext.core, fb);
m_hwaccel = true;
}
}
void CoreController::updateKeys() {
int activeKeys = m_activeKeys | updateAutofire() | m_inputController->pollEvents();
m_threadContext.core->setKeys(m_threadContext.core, activeKeys);
@ -823,6 +840,7 @@ int CoreController::updateAutofire() {
void CoreController::finishFrame() {
QMutexLocker locker(&m_mutex);
if (!m_hwaccel) {
memcpy(m_completeBuffer.data(), m_activeBuffer->constData(), m_activeBuffer->size());
// TODO: Generalize this to triple buffering?
@ -833,7 +851,7 @@ void CoreController::finishFrame() {
// Copy contents to avoid issues when doing frameskip
memcpy(m_activeBuffer->data(), m_completeBuffer.constData(), m_activeBuffer->size());
m_threadContext.core->setVideoBuffer(m_threadContext.core, reinterpret_cast<color_t*>(m_activeBuffer->data()), screenDimensions().width());
}
for (auto& action : m_frameActions) {
action();
}

View File

@ -46,6 +46,10 @@ public:
static const bool VIDEO_SYNC = false;
static const bool AUDIO_SYNC = true;
enum class Feature {
OPENGL = mCORE_FEATURE_OPENGL,
};
class Interrupter {
public:
Interrupter(CoreController*, bool fromThread = false);
@ -69,6 +73,8 @@ public:
mPlatform platform() const;
QSize screenDimensions() const;
bool supportsFeature(Feature feature) const { return m_threadContext.core->supportsFeature(m_threadContext.core, static_cast<mCoreFeature>(feature)); }
bool hardwareAccelerated() const { return m_hwaccel; }
void loadConfig(ConfigController*);
@ -154,6 +160,8 @@ public slots:
void startVideoLog(const QString& path);
void endVideoLog();
void setFramebufferHandle(int fb);
signals:
void started();
void paused();
@ -188,6 +196,7 @@ private:
QByteArray m_buffers[2];
QByteArray* m_activeBuffer;
QByteArray m_completeBuffer;
bool m_hwaccel = false;
std::unique_ptr<mCacheSet> m_cacheSet;
std::unique_ptr<Override> m_override;

View File

@ -49,6 +49,7 @@ public:
virtual bool supportsShaders() const = 0;
virtual VideoShader* shaders() = 0;
virtual VideoProxy* videoProxy() { return nullptr; }
virtual int framebufferHandle() { return -1; }
signals:
void showCursor();

View File

@ -18,7 +18,7 @@
#ifdef BUILD_GL
#include "platform/opengl/gl.h"
#endif
#if !defined(_WIN32) || defined(USE_EPOXY)
#ifdef BUILD_GLES2
#include "platform/opengl/gles2.h"
#ifdef _WIN32
#include <epoxy/wgl.h>
@ -195,6 +195,10 @@ VideoProxy* DisplayGL::videoProxy() {
return nullptr;
}
int DisplayGL::framebufferHandle() {
return m_painter->glTex();
}
PainterGL::PainterGL(int majorVersion, VideoProxy* proxy, QGLWidget* parent)
: m_gl(parent)
, m_videoProxy(proxy)
@ -202,7 +206,7 @@ PainterGL::PainterGL(int majorVersion, VideoProxy* proxy, QGLWidget* parent)
#ifdef BUILD_GL
mGLContext* glBackend;
#endif
#if !defined(_WIN32) || defined(USE_EPOXY)
#ifdef BUILD_GLES2
mGLES2Context* gl2Backend;
#endif
@ -213,7 +217,7 @@ PainterGL::PainterGL(int majorVersion, VideoProxy* proxy, QGLWidget* parent)
QStringList extensions = QString(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))).split(' ');
#if !defined(_WIN32) || defined(USE_EPOXY)
#ifdef BUILD_GLES2
if (extensions.contains("GL_ARB_framebuffer_object") && majorVersion >= 2) {
gl2Backend = static_cast<mGLES2Context*>(malloc(sizeof(mGLES2Context)));
mGLES2ContextCreate(gl2Backend);
@ -239,7 +243,7 @@ PainterGL::PainterGL(int majorVersion, VideoProxy* proxy, QGLWidget* parent)
};
m_backend->init(m_backend, reinterpret_cast<WHandle>(m_gl->winId()));
#if !defined(_WIN32) || defined(USE_EPOXY)
#ifdef BUILD_GLES2
if (m_supportsShaders) {
m_shader.preprocessShader = static_cast<void*>(&reinterpret_cast<mGLES2Context*>(m_backend)->initialShader);
}
@ -266,7 +270,7 @@ PainterGL::~PainterGL() {
#if defined(_WIN32) && defined(USE_EPOXY)
epoxy_handle_external_wglMakeCurrent();
#endif
#if !defined(_WIN32) || defined(USE_EPOXY)
#ifdef BUILD_GLES2
if (m_shader.passes) {
mGLES2ShaderFree(&m_shader);
}
@ -339,7 +343,7 @@ void PainterGL::start() {
epoxy_handle_external_wglMakeCurrent();
#endif
#if !defined(_WIN32) || defined(USE_EPOXY)
#ifdef BUILD_GLES2
if (m_supportsShaders && m_shader.passes) {
mGLES2ShaderAttach(reinterpret_cast<mGLES2Context*>(m_backend), static_cast<mGLES2Shader*>(m_shader.passes), m_shader.nPasses);
}
@ -422,7 +426,8 @@ void PainterGL::performDraw() {
void PainterGL::enqueue(const uint32_t* backing) {
m_mutex.lock();
uint32_t* buffer;
uint32_t* buffer = nullptr;
if (backing) {
if (m_free.isEmpty()) {
buffer = m_queue.dequeue();
} else {
@ -430,6 +435,7 @@ void PainterGL::enqueue(const uint32_t* backing) {
}
QSize size = m_context->screenDimensions();
memcpy(buffer, backing, size.width() * size.height() * BYTES_PER_PIXEL);
}
m_queue.enqueue(buffer);
m_mutex.unlock();
}
@ -441,8 +447,10 @@ void PainterGL::dequeue() {
return;
}
uint32_t* buffer = m_queue.dequeue();
if (buffer) {
m_backend->postFrame(m_backend, buffer);
m_free.append(buffer);
}
m_mutex.unlock();
}
@ -451,8 +459,10 @@ void PainterGL::dequeueAll() {
m_mutex.lock();
while (!m_queue.isEmpty()) {
buffer = m_queue.dequeue();
if (buffer) {
m_free.append(buffer);
}
}
if (buffer) {
m_backend->postFrame(m_backend, buffer);
}
@ -464,7 +474,7 @@ void PainterGL::setShaders(struct VDir* dir) {
return;
}
if (!m_active) {
#if !defined(_WIN32) || defined(USE_EPOXY)
#ifdef BUILD_GLES2
m_gl->makeCurrent();
#if defined(_WIN32) && defined(USE_EPOXY)
epoxy_handle_external_wglMakeCurrent();
@ -489,7 +499,7 @@ void PainterGL::clearShaders() {
return;
}
if (!m_active) {
#if !defined(_WIN32) || defined(USE_EPOXY)
#ifdef BUILD_GLES2
m_gl->makeCurrent();
#if defined(_WIN32) && defined(USE_EPOXY)
epoxy_handle_external_wglMakeCurrent();
@ -509,4 +519,19 @@ VideoShader* PainterGL::shaders() {
return &m_shader;
}
int PainterGL::glTex() {
#ifdef BUILD_GLES2
if (supportsShaders()) {
mGLES2Context* gl2Backend = reinterpret_cast<mGLES2Context*>(m_backend);
return gl2Backend->tex;
}
#endif
#ifdef BUILD_GL
mGLContext* glBackend = reinterpret_cast<mGLContext*>(m_backend);
return glBackend->tex;
#else
return -1;
#endif
}
#endif

View File

@ -52,6 +52,7 @@ public:
bool supportsShaders() const override;
VideoShader* shaders() override;
VideoProxy* videoProxy() override;
int framebufferHandle() override;
public slots:
void stopDrawing() override;
@ -111,6 +112,8 @@ public slots:
void clearShaders();
VideoShader* shaders();
int glTex();
private:
void performDraw();
void dequeue();

View File

@ -851,6 +851,10 @@ void Window::unimplementedBiosCall(int call) {
void Window::reloadDisplayDriver() {
if (m_controller) {
if (m_controller->hardwareAccelerated()) {
mustRestart();
return;
}
m_display->stopDrawing();
detachWidget(m_display.get());
}
@ -1715,10 +1719,17 @@ void Window::setController(CoreController* controller, const QString& fname) {
reloadDisplayDriver();
}
if (m_config->getOption("hwaccelVideo").toInt() && m_display->supportsShaders() && controller->supportsFeature(CoreController::Feature::OPENGL)) {
if (m_display->videoProxy()) {
m_display->videoProxy()->attach(controller);
}
int fb = m_display->framebufferHandle();
if (fb >= 0) {
controller->setFramebufferHandle(fb);
}
}
m_controller = std::shared_ptr<CoreController>(controller);
m_inputController.recalibrateAxes();
m_controller->setInputController(&m_inputController);

View File

@ -77,12 +77,11 @@ if(BUILD_PANDORA)
else()
if(BUILD_GL)
list(APPEND MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/gl-sdl.c)
list(APPEND PLATFORM_SRC ${CMAKE_SOURCE_DIR}/src/platform/opengl/gl.c ${CMAKE_SOURCE_DIR}/src/platform/sdl/gl-common.c)
include_directories(${OPENGL_INCLUDE_DIR})
list(APPEND PLATFORM_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/gl-common.c)
endif()
if(BUILD_GLES2)
list(APPEND MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/gles2-sdl.c)
list(APPEND PLATFORM_SRC ${CMAKE_SOURCE_DIR}/src/platform/opengl/gles2.c ${CMAKE_SOURCE_DIR}/src/platform/sdl/gl-common.c)
list(APPEND PLATFORM_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/gl-common.c)
include_directories(${OPENGLES2_INCLUDE_DIR})
endif()
if(NOT BUILD_GL AND NOT BUILD_GLES2)

View File

@ -35,7 +35,9 @@ bool mSDLGLES2Init(struct mSDLRenderer* renderer) {
#endif
size_t size = renderer->width * renderer->height * BYTES_PER_PIXEL;
#ifndef __APPLE__
#ifdef _WIN32
renderer->outputBuffer = _aligned_malloc(size, 16);
#elif !defined(__APPLE__)
renderer->outputBuffer = memalign(16, size);
#else
posix_memalign((void**) &renderer->outputBuffer, 16, size);

View File

@ -31,6 +31,7 @@ while [ $# -gt 0 ]; do
rmdep libav
rmdep libedit
rmdep libelf
rmdep libgl
rmdep libpng
rmdep libzip
rmdep libmagickwand
@ -45,6 +46,7 @@ while [ $# -gt 0 ]; do
rmdep libav
rmdep libedit
rmdep libelf
rmdep libgl
rmdep libpng
rmdep qt
rmdep libzip