mirror of https://github.com/mgba-emu/mgba.git
Core: Improve OpenGL integration, update Qt to use improvements
This commit is contained in:
parent
49a9da3e5c
commit
8450417086
|
@ -57,7 +57,7 @@ if(NOT LIBMGBA_ONLY)
|
||||||
set(BUILD_SHARED ON CACHE BOOL "Build a shared library")
|
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(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_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(BUILD_GLES3 OFF CACHE BOOL "Build with OpenGL|ES 3")
|
||||||
set(USE_EPOXY ON CACHE STRING "Build with libepoxy")
|
set(USE_EPOXY ON CACHE STRING "Build with libepoxy")
|
||||||
set(DISABLE_DEPS OFF CACHE BOOL "Build without dependencies")
|
set(DISABLE_DEPS OFF CACHE BOOL "Build without dependencies")
|
||||||
|
@ -447,7 +447,7 @@ set(FEATURE_DEFINES)
|
||||||
set(FEATURE_FLAGS)
|
set(FEATURE_FLAGS)
|
||||||
set(FEATURES)
|
set(FEATURES)
|
||||||
set(ENABLES)
|
set(ENABLES)
|
||||||
if(CMAKE_SYSTEM_NAME MATCHES .*BSD)
|
if(CMAKE_SYSTEM_NAME MATCHES ".*BSD|DragonFly")
|
||||||
set(LIBEDIT_LIBRARIES -ledit)
|
set(LIBEDIT_LIBRARIES -ledit)
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL OpenBSD)
|
if (CMAKE_SYSTEM_NAME STREQUAL OpenBSD)
|
||||||
list(APPEND LIBEDIT_LIBRARIES -ltermcap)
|
list(APPEND LIBEDIT_LIBRARIES -ltermcap)
|
||||||
|
@ -462,9 +462,9 @@ if(BUILD_GL)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
if(NOT BUILD_GL)
|
if(NOT BUILD_GL)
|
||||||
set(OPENGLE_LIBRARY "" CACHE PATH "" FORCE)
|
set(OPENGL_LIBRARY "" CACHE PATH "" FORCE)
|
||||||
endif()
|
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_path(OPENGLES2_INCLUDE_DIR NAMES GLES2/gl2.h)
|
||||||
find_library(OPENGLES2_LIBRARY NAMES GLESv2 GLESv2_CM)
|
find_library(OPENGLES2_LIBRARY NAMES GLESv2 GLESv2_CM)
|
||||||
if(NOT OPENGLES2_INCLUDE_DIR OR NOT OPENGLES2_LIBRARY)
|
if(NOT OPENGLES2_INCLUDE_DIR OR NOT OPENGLES2_LIBRARY)
|
||||||
|
@ -474,6 +474,16 @@ endif()
|
||||||
if(NOT BUILD_GLES2)
|
if(NOT BUILD_GLES2)
|
||||||
set(OPENGLES2_LIBRARY "" CACHE PATH "" FORCE)
|
set(OPENGLES2_LIBRARY "" CACHE PATH "" FORCE)
|
||||||
endif()
|
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)
|
if(BUILD_GLES3)
|
||||||
find_path(OPENGLES3_INCLUDE_DIR NAMES GLES3/gl3.h)
|
find_path(OPENGLES3_INCLUDE_DIR NAMES GLES3/gl3.h)
|
||||||
find_library(OPENGLES3_LIBRARY NAMES GLESv3 GLESv2)
|
find_library(OPENGLES3_LIBRARY NAMES GLESv3 GLESv2)
|
||||||
|
@ -733,6 +743,10 @@ if(USE_EPOXY)
|
||||||
link_directories(${EPOXY_LIBRARY_DIRS})
|
link_directories(${EPOXY_LIBRARY_DIRS})
|
||||||
set(OPENGLES2_LIBRARY ${EPOXY_LIBRARIES})
|
set(OPENGLES2_LIBRARY ${EPOXY_LIBRARIES})
|
||||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libepoxy0")
|
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()
|
endif()
|
||||||
|
|
||||||
if(USE_SQLITE3)
|
if(USE_SQLITE3)
|
||||||
|
|
|
@ -64,6 +64,7 @@ struct mCore {
|
||||||
void (*deinit)(struct mCore*);
|
void (*deinit)(struct mCore*);
|
||||||
|
|
||||||
enum mPlatform (*platform)(const struct mCore*);
|
enum mPlatform (*platform)(const struct mCore*);
|
||||||
|
bool (*supportsFeature)(const struct mCore*, enum mCoreFeature);
|
||||||
|
|
||||||
void (*setSync)(struct mCore*, struct mCoreSync*);
|
void (*setSync)(struct mCore*, struct mCoreSync*);
|
||||||
void (*loadConfig)(struct mCore*, const struct mCoreConfig*);
|
void (*loadConfig)(struct mCore*, const struct mCoreConfig*);
|
||||||
|
|
|
@ -80,6 +80,10 @@ enum mColorFormat {
|
||||||
mCOLOR_ANY = -1
|
mCOLOR_ANY = -1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum mCoreFeature {
|
||||||
|
mCORE_FEATURE_OPENGL = 1,
|
||||||
|
};
|
||||||
|
|
||||||
struct mCoreCallbacks {
|
struct mCoreCallbacks {
|
||||||
void* context;
|
void* context;
|
||||||
void (*videoFrameStarted)(void* context);
|
void (*videoFrameStarted)(void* context);
|
||||||
|
|
|
@ -16,6 +16,8 @@ CXX_GUARD_START
|
||||||
#include <mgba/internal/gba/renderers/common.h>
|
#include <mgba/internal/gba/renderers/common.h>
|
||||||
#include <mgba/internal/gba/video.h>
|
#include <mgba/internal/gba/video.h>
|
||||||
|
|
||||||
|
#if defined(BUILD_GLES2) || defined(BUILD_GLES3)
|
||||||
|
|
||||||
#ifdef USE_EPOXY
|
#ifdef USE_EPOXY
|
||||||
#include <epoxy/gl.h>
|
#include <epoxy/gl.h>
|
||||||
#elif defined(BUILD_GL)
|
#elif defined(BUILD_GL)
|
||||||
|
@ -27,7 +29,7 @@ CXX_GUARD_START
|
||||||
#include <GL/glext.h>
|
#include <GL/glext.h>
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#include <GLES2/gl2.h>
|
#include <GLES3/gl3.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct GBAVideoGLAffine {
|
struct GBAVideoGLAffine {
|
||||||
|
@ -137,6 +139,9 @@ struct GBAVideoGLRenderer {
|
||||||
|
|
||||||
GLuint outputTex;
|
GLuint outputTex;
|
||||||
|
|
||||||
|
#ifdef BUILD_GLES3
|
||||||
|
uint16_t shadowPalette[512];
|
||||||
|
#endif
|
||||||
GLuint paletteTex;
|
GLuint paletteTex;
|
||||||
bool paletteDirty;
|
bool paletteDirty;
|
||||||
|
|
||||||
|
@ -182,6 +187,8 @@ struct GBAVideoGLRenderer {
|
||||||
|
|
||||||
void GBAVideoGLRendererCreate(struct GBAVideoGLRenderer* renderer);
|
void GBAVideoGLRendererCreate(struct GBAVideoGLRenderer* renderer);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
CXX_GUARD_END
|
CXX_GUARD_END
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -138,6 +138,14 @@ static enum mPlatform _GBCorePlatform(const struct mCore* core) {
|
||||||
return PLATFORM_GB;
|
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) {
|
static void _GBCoreSetSync(struct mCore* core, struct mCoreSync* sync) {
|
||||||
struct GB* gb = core->board;
|
struct GB* gb = core->board;
|
||||||
gb->sync = sync;
|
gb->sync = sync;
|
||||||
|
@ -888,6 +896,7 @@ struct mCore* GBCoreCreate(void) {
|
||||||
core->init = _GBCoreInit;
|
core->init = _GBCoreInit;
|
||||||
core->deinit = _GBCoreDeinit;
|
core->deinit = _GBCoreDeinit;
|
||||||
core->platform = _GBCorePlatform;
|
core->platform = _GBCorePlatform;
|
||||||
|
core->supportsFeature = _GBCoreSupportsFeature;
|
||||||
core->setSync = _GBCoreSetSync;
|
core->setSync = _GBCoreSetSync;
|
||||||
core->loadConfig = _GBCoreLoadConfig;
|
core->loadConfig = _GBCoreLoadConfig;
|
||||||
core->desiredVideoDimensions = _GBCoreDesiredVideoDimensions;
|
core->desiredVideoDimensions = _GBCoreDesiredVideoDimensions;
|
||||||
|
|
|
@ -17,7 +17,9 @@
|
||||||
#ifndef DISABLE_THREADING
|
#ifndef DISABLE_THREADING
|
||||||
#include <mgba/feature/thread-proxy.h>
|
#include <mgba/feature/thread-proxy.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef BUILD_GLES2
|
||||||
#include <mgba/internal/gba/renderers/gl.h>
|
#include <mgba/internal/gba/renderers/gl.h>
|
||||||
|
#endif
|
||||||
#include <mgba/internal/gba/renderers/proxy.h>
|
#include <mgba/internal/gba/renderers/proxy.h>
|
||||||
#include <mgba/internal/gba/renderers/video-software.h>
|
#include <mgba/internal/gba/renderers/video-software.h>
|
||||||
#include <mgba/internal/gba/savedata.h>
|
#include <mgba/internal/gba/savedata.h>
|
||||||
|
@ -124,7 +126,9 @@ struct mVideoLogContext;
|
||||||
struct GBACore {
|
struct GBACore {
|
||||||
struct mCore d;
|
struct mCore d;
|
||||||
struct GBAVideoSoftwareRenderer renderer;
|
struct GBAVideoSoftwareRenderer renderer;
|
||||||
|
#ifdef BUILD_GLES2
|
||||||
struct GBAVideoGLRenderer glRenderer;
|
struct GBAVideoGLRenderer glRenderer;
|
||||||
|
#endif
|
||||||
struct GBAVideoProxyRenderer proxyRenderer;
|
struct GBAVideoProxyRenderer proxyRenderer;
|
||||||
struct mVideoLogContext* logContext;
|
struct mVideoLogContext* logContext;
|
||||||
struct mCoreCallbacks logCallbacks;
|
struct mCoreCallbacks logCallbacks;
|
||||||
|
@ -170,8 +174,10 @@ static bool _GBACoreInit(struct mCore* core) {
|
||||||
GBAVideoSoftwareRendererCreate(&gbacore->renderer);
|
GBAVideoSoftwareRendererCreate(&gbacore->renderer);
|
||||||
gbacore->renderer.outputBuffer = NULL;
|
gbacore->renderer.outputBuffer = NULL;
|
||||||
|
|
||||||
|
#ifdef BUILD_GLES2
|
||||||
GBAVideoGLRendererCreate(&gbacore->glRenderer);
|
GBAVideoGLRendererCreate(&gbacore->glRenderer);
|
||||||
gbacore->glRenderer.outputTex = -1;
|
gbacore->glRenderer.outputTex = -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef DISABLE_THREADING
|
#ifndef DISABLE_THREADING
|
||||||
mVideoThreadProxyCreate(&gbacore->threadProxy);
|
mVideoThreadProxyCreate(&gbacore->threadProxy);
|
||||||
|
@ -212,6 +218,20 @@ static enum mPlatform _GBACorePlatform(const struct mCore* core) {
|
||||||
return PLATFORM_GBA;
|
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) {
|
static void _GBACoreSetSync(struct mCore* core, struct mCoreSync* sync) {
|
||||||
struct GBA* gba = core->board;
|
struct GBA* gba = core->board;
|
||||||
gba->sync = sync;
|
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) {
|
static void _GBACoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) {
|
||||||
|
#ifdef BUILD_GLES2
|
||||||
struct GBACore* gbacore = (struct GBACore*) core;
|
struct GBACore* gbacore = (struct GBACore*) core;
|
||||||
int fakeBool;
|
|
||||||
int scale = gbacore->glRenderer.scale;
|
int scale = gbacore->glRenderer.scale;
|
||||||
|
#else
|
||||||
|
int scale = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
*width = GBA_VIDEO_HORIZONTAL_PIXELS * scale;
|
*width = GBA_VIDEO_HORIZONTAL_PIXELS * scale;
|
||||||
*height = GBA_VIDEO_VERTICAL_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) {
|
static void _GBACoreSetVideoGLTex(struct mCore* core, unsigned texid) {
|
||||||
|
#ifdef BUILD_GLES2
|
||||||
struct GBACore* gbacore = (struct GBACore*) core;
|
struct GBACore* gbacore = (struct GBACore*) core;
|
||||||
gbacore->glRenderer.outputTex = texid;
|
gbacore->glRenderer.outputTex = texid;
|
||||||
|
#else
|
||||||
|
UNUSED(core);
|
||||||
|
UNUSED(texid);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _GBACoreGetPixels(struct mCore* core, const void** buffer, size_t* stride) {
|
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) {
|
static void _GBACoreReset(struct mCore* core) {
|
||||||
struct GBACore* gbacore = (struct GBACore*) core;
|
struct GBACore* gbacore = (struct GBACore*) core;
|
||||||
struct GBA* gba = (struct GBA*) core->board;
|
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;
|
struct GBAVideoRenderer* renderer;
|
||||||
if (gbacore->renderer.outputBuffer) {
|
if (gbacore->renderer.outputBuffer) {
|
||||||
renderer = &gbacore->renderer.d;
|
renderer = &gbacore->renderer.d;
|
||||||
}
|
}
|
||||||
int fakeBool;
|
int fakeBool;
|
||||||
|
#ifdef BUILD_GLES2
|
||||||
if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) {
|
if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) {
|
||||||
renderer = &gbacore->glRenderer.d;
|
renderer = &gbacore->glRenderer.d;
|
||||||
mCoreConfigGetIntValue(&core->config, "videoScale", &gbacore->glRenderer.scale);
|
mCoreConfigGetIntValue(&core->config, "videoScale", &gbacore->glRenderer.scale);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#ifndef DISABLE_THREADING
|
#ifndef DISABLE_THREADING
|
||||||
if (mCoreConfigGetIntValue(&core->config, "threadedVideo", &fakeBool) && fakeBool) {
|
if (mCoreConfigGetIntValue(&core->config, "threadedVideo", &fakeBool) && fakeBool) {
|
||||||
if (!core->videoLogger) {
|
if (!core->videoLogger) {
|
||||||
|
@ -952,6 +986,7 @@ struct mCore* GBACoreCreate(void) {
|
||||||
core->init = _GBACoreInit;
|
core->init = _GBACoreInit;
|
||||||
core->deinit = _GBACoreDeinit;
|
core->deinit = _GBACoreDeinit;
|
||||||
core->platform = _GBACorePlatform;
|
core->platform = _GBACorePlatform;
|
||||||
|
core->supportsFeature = _GBACoreSupportsFeature;
|
||||||
core->setSync = _GBACoreSetSync;
|
core->setSync = _GBACoreSetSync;
|
||||||
core->loadConfig = _GBACoreLoadConfig;
|
core->loadConfig = _GBACoreLoadConfig;
|
||||||
core->desiredVideoDimensions = _GBACoreDesiredVideoDimensions;
|
core->desiredVideoDimensions = _GBACoreDesiredVideoDimensions;
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
#include <mgba/internal/gba/renderers/gl.h>
|
#include <mgba/internal/gba/renderers/gl.h>
|
||||||
|
|
||||||
|
#if defined(BUILD_GLES2) || defined(BUILD_GLES3)
|
||||||
|
|
||||||
#include <mgba/core/cache-set.h>
|
#include <mgba/core/cache-set.h>
|
||||||
#include <mgba/internal/arm/macros.h>
|
#include <mgba/internal/arm/macros.h>
|
||||||
#include <mgba/internal/gba/io.h>
|
#include <mgba/internal/gba/io.h>
|
||||||
|
@ -90,7 +92,7 @@ static const char* const _renderTile256 =
|
||||||
" return color;\n"
|
" return color;\n"
|
||||||
"}";
|
"}";
|
||||||
|
|
||||||
const static struct GBAVideoGLUniform _uniformsMode0[] = {
|
static const struct GBAVideoGLUniform _uniformsMode0[] = {
|
||||||
{ "loc", GBA_GL_VS_LOC, },
|
{ "loc", GBA_GL_VS_LOC, },
|
||||||
{ "maxPos", GBA_GL_VS_MAXPOS, },
|
{ "maxPos", GBA_GL_VS_MAXPOS, },
|
||||||
{ "vram", GBA_GL_BG_VRAM, },
|
{ "vram", GBA_GL_BG_VRAM, },
|
||||||
|
@ -155,7 +157,7 @@ static const char* const _fetchTileNoOverflow =
|
||||||
" return renderTile(coord);\n"
|
" return renderTile(coord);\n"
|
||||||
"}";
|
"}";
|
||||||
|
|
||||||
const static struct GBAVideoGLUniform _uniformsMode2[] = {
|
static const struct GBAVideoGLUniform _uniformsMode2[] = {
|
||||||
{ "loc", GBA_GL_VS_LOC, },
|
{ "loc", GBA_GL_VS_LOC, },
|
||||||
{ "maxPos", GBA_GL_VS_MAXPOS, },
|
{ "maxPos", GBA_GL_VS_MAXPOS, },
|
||||||
{ "vram", GBA_GL_BG_VRAM, },
|
{ "vram", GBA_GL_BG_VRAM, },
|
||||||
|
@ -221,7 +223,7 @@ static const char* const _renderMode2 =
|
||||||
" flags = inflags / flagCoeff;\n"
|
" flags = inflags / flagCoeff;\n"
|
||||||
"}";
|
"}";
|
||||||
|
|
||||||
const static struct GBAVideoGLUniform _uniformsObj[] = {
|
static const struct GBAVideoGLUniform _uniformsObj[] = {
|
||||||
{ "loc", GBA_GL_VS_LOC, },
|
{ "loc", GBA_GL_VS_LOC, },
|
||||||
{ "maxPos", GBA_GL_VS_MAXPOS, },
|
{ "maxPos", GBA_GL_VS_MAXPOS, },
|
||||||
{ "vram", GBA_GL_OBJ_VRAM, },
|
{ "vram", GBA_GL_OBJ_VRAM, },
|
||||||
|
@ -268,7 +270,7 @@ static const char* const _renderObj =
|
||||||
" window = objwin.yz;\n"
|
" window = objwin.yz;\n"
|
||||||
"}";
|
"}";
|
||||||
|
|
||||||
const static struct GBAVideoGLUniform _uniformsComposite[] = {
|
static const struct GBAVideoGLUniform _uniformsComposite[] = {
|
||||||
{ "loc", GBA_GL_VS_LOC, },
|
{ "loc", GBA_GL_VS_LOC, },
|
||||||
{ "maxPos", GBA_GL_VS_MAXPOS, },
|
{ "maxPos", GBA_GL_VS_MAXPOS, },
|
||||||
{ "scale", GBA_GL_COMPOSITE_SCALE, },
|
{ "scale", GBA_GL_COMPOSITE_SCALE, },
|
||||||
|
@ -329,7 +331,7 @@ static const char* const _composite =
|
||||||
" }\n"
|
" }\n"
|
||||||
"}";
|
"}";
|
||||||
|
|
||||||
const static struct GBAVideoGLUniform _uniformsFinalize[] = {
|
static const struct GBAVideoGLUniform _uniformsFinalize[] = {
|
||||||
{ "loc", GBA_GL_VS_LOC, },
|
{ "loc", GBA_GL_VS_LOC, },
|
||||||
{ "maxPos", GBA_GL_VS_MAXPOS, },
|
{ "maxPos", GBA_GL_VS_MAXPOS, },
|
||||||
{ "scale", GBA_GL_FINALIZE_SCALE, },
|
{ "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);
|
mLOG(GBA_VIDEO, ERROR, "Program link failure: %s", log);
|
||||||
}
|
}
|
||||||
glDeleteShader(fs);
|
glDeleteShader(fs);
|
||||||
|
#ifndef BUILD_GLES3
|
||||||
glBindFragDataLocation(program, 0, "color");
|
glBindFragDataLocation(program, 0, "color");
|
||||||
glBindFragDataLocation(program, 1, "flags");
|
glBindFragDataLocation(program, 1, "flags");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _initFramebufferTexture(GLuint tex, GLenum format, GLenum attachment, int scale) {
|
static void _initFramebufferTexture(GLuint tex, GLenum format, GLenum attachment, int scale) {
|
||||||
|
@ -550,18 +554,24 @@ void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer) {
|
||||||
shaderBuffer[2] = _renderTile16;
|
shaderBuffer[2] = _renderTile16;
|
||||||
_compileShader(glRenderer, glRenderer->objProgram[0], shaderBuffer, 3, vs, log);
|
_compileShader(glRenderer, glRenderer->objProgram[0], shaderBuffer, 3, vs, log);
|
||||||
_lookupUniforms(glRenderer->objProgram[0], glRenderer->objUniforms[0], _uniformsObj);
|
_lookupUniforms(glRenderer->objProgram[0], glRenderer->objUniforms[0], _uniformsObj);
|
||||||
|
#ifndef BUILD_GLES3
|
||||||
glBindFragDataLocation(glRenderer->objProgram[0], 2, "window");
|
glBindFragDataLocation(glRenderer->objProgram[0], 2, "window");
|
||||||
|
#endif
|
||||||
|
|
||||||
shaderBuffer[2] = _renderTile256;
|
shaderBuffer[2] = _renderTile256;
|
||||||
_compileShader(glRenderer, glRenderer->objProgram[1], shaderBuffer, 3, vs, log);
|
_compileShader(glRenderer, glRenderer->objProgram[1], shaderBuffer, 3, vs, log);
|
||||||
_lookupUniforms(glRenderer->objProgram[1], glRenderer->objUniforms[1], _uniformsObj);
|
_lookupUniforms(glRenderer->objProgram[1], glRenderer->objUniforms[1], _uniformsObj);
|
||||||
|
#ifndef BUILD_GLES3
|
||||||
glBindFragDataLocation(glRenderer->objProgram[1], 2, "window");
|
glBindFragDataLocation(glRenderer->objProgram[1], 2, "window");
|
||||||
|
#endif
|
||||||
|
|
||||||
shaderBuffer[1] = _composite;
|
shaderBuffer[1] = _composite;
|
||||||
_compileShader(glRenderer, glRenderer->compositeProgram, shaderBuffer, 2, vs, log);
|
_compileShader(glRenderer, glRenderer->compositeProgram, shaderBuffer, 2, vs, log);
|
||||||
_lookupUniforms(glRenderer->compositeProgram, glRenderer->compositeUniforms, _uniformsComposite);
|
_lookupUniforms(glRenderer->compositeProgram, glRenderer->compositeUniforms, _uniformsComposite);
|
||||||
|
#ifndef BUILD_GLES3
|
||||||
glBindFragDataLocation(glRenderer->compositeProgram, 2, "oldColor");
|
glBindFragDataLocation(glRenderer->compositeProgram, 2, "oldColor");
|
||||||
glBindFragDataLocation(glRenderer->compositeProgram, 3, "oldFlags");
|
glBindFragDataLocation(glRenderer->compositeProgram, 3, "oldFlags");
|
||||||
|
#endif
|
||||||
|
|
||||||
shaderBuffer[1] = _finalize;
|
shaderBuffer[1] = _finalize;
|
||||||
_compileShader(glRenderer, glRenderer->finalizeProgram, shaderBuffer, 2, vs, log);
|
_compileShader(glRenderer, glRenderer->finalizeProgram, shaderBuffer, 2, vs, log);
|
||||||
|
@ -585,7 +595,6 @@ void GBAVideoGLRendererDeinit(struct GBAVideoRenderer* renderer) {
|
||||||
glDeleteProgram(glRenderer->bgProgram[3]);
|
glDeleteProgram(glRenderer->bgProgram[3]);
|
||||||
glDeleteProgram(glRenderer->bgProgram[4]);
|
glDeleteProgram(glRenderer->bgProgram[4]);
|
||||||
glDeleteProgram(glRenderer->bgProgram[5]);
|
glDeleteProgram(glRenderer->bgProgram[5]);
|
||||||
glDeleteProgram(glRenderer->bgProgram[6]);
|
|
||||||
glDeleteProgram(glRenderer->objProgram[0]);
|
glDeleteProgram(glRenderer->objProgram[0]);
|
||||||
glDeleteProgram(glRenderer->objProgram[1]);
|
glDeleteProgram(glRenderer->objProgram[1]);
|
||||||
glDeleteProgram(glRenderer->compositeProgram);
|
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) {
|
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(address);
|
||||||
UNUSED(value);
|
UNUSED(value);
|
||||||
struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer;
|
#endif
|
||||||
glRenderer->paletteDirty = true;
|
glRenderer->paletteDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -822,7 +835,11 @@ void GBAVideoGLRendererDrawScanline(struct GBAVideoRenderer* renderer, int y) {
|
||||||
struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer;
|
struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer;
|
||||||
if (glRenderer->paletteDirty) {
|
if (glRenderer->paletteDirty) {
|
||||||
glBindTexture(GL_TEXTURE_2D, glRenderer->paletteTex);
|
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);
|
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;
|
glRenderer->paletteDirty = false;
|
||||||
}
|
}
|
||||||
int i;
|
int i;
|
||||||
|
@ -841,33 +858,33 @@ void GBAVideoGLRendererDrawScanline(struct GBAVideoRenderer* renderer, int y) {
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, glRenderer->fbo[GBA_GL_FBO_COMPOSITE]);
|
glBindFramebuffer(GL_FRAMEBUFFER, glRenderer->fbo[GBA_GL_FBO_COMPOSITE]);
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
glScissor(0, y * glRenderer->scale, GBA_VIDEO_HORIZONTAL_PIXELS * glRenderer->scale, glRenderer->scale);
|
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);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
if (y == 0) {
|
if (y == 0) {
|
||||||
glDisable(GL_SCISSOR_TEST);
|
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,
|
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);
|
(glRenderer->blendEffect == BLEND_ALPHA ? glRenderer->blda : glRenderer->bldy) / 16.f, glRenderer->bldb / 16.f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
glClearColor(0, 0, 0, 0);
|
glClearColor(0, 0, 0, 0);
|
||||||
glDrawBuffer(GL_COLOR_ATTACHMENT3);
|
glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT3 });
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, glRenderer->fbo[GBA_GL_FBO_OBJ]);
|
glBindFramebuffer(GL_FRAMEBUFFER, glRenderer->fbo[GBA_GL_FBO_OBJ]);
|
||||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT0 });
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
glDrawBuffer(GL_COLOR_ATTACHMENT1);
|
glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT1 });
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
for (i = 0; i < 4; ++i) {
|
for (i = 0; i < 4; ++i) {
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, glRenderer->bg[i].fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, glRenderer->bg[i].fbo);
|
||||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT0 });
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
glDrawBuffer(GL_COLOR_ATTACHMENT1);
|
glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT1 });
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT0 });
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
}
|
}
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
@ -1310,3 +1327,5 @@ void GBAVideoGLRendererDrawWindow(struct GBAVideoGLRenderer* renderer, int y) {
|
||||||
}
|
}
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -47,17 +47,6 @@ if(APPLE)
|
||||||
endif()
|
endif()
|
||||||
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)
|
get_target_property(QT_TYPE Qt5::Core TYPE)
|
||||||
if(QT_TYPE STREQUAL STATIC_LIBRARY)
|
if(QT_TYPE STREQUAL STATIC_LIBRARY)
|
||||||
set(QT_STATIC ON)
|
set(QT_STATIC ON)
|
||||||
|
@ -245,7 +234,7 @@ if(NOT DEFINED DATADIR)
|
||||||
set(DATADIR ${CMAKE_INSTALL_DATADIR}/${BINARY_NAME})
|
set(DATADIR ${CMAKE_INSTALL_DATADIR}/${BINARY_NAME})
|
||||||
endif()
|
endif()
|
||||||
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)
|
install(DIRECTORY ${CMAKE_SOURCE_DIR}/res/shaders DESTINATION ${DATADIR} COMPONENT ${BINARY_NAME}-qt)
|
||||||
endif()
|
endif()
|
||||||
install(FILES ${CMAKE_SOURCE_DIR}/res/nointro.dat DESTINATION ${DATADIR} COMPONENT ${BINARY_NAME}-qt)
|
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}")
|
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)
|
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})
|
list(APPEND QT_LIBRARIES Qt5::OpenGL ${OPENGL_LIBRARY} ${OPENGLES2_LIBRARY})
|
||||||
endif()
|
endif()
|
||||||
if(QT_STATIC)
|
if(QT_STATIC)
|
||||||
|
|
|
@ -40,16 +40,6 @@ CoreController::CoreController(mCore* core, QObject* parent)
|
||||||
m_threadContext.core = core;
|
m_threadContext.core = core;
|
||||||
m_threadContext.userData = this;
|
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]() {
|
m_resetActions.append([this]() {
|
||||||
if (m_autoload) {
|
if (m_autoload) {
|
||||||
mCoreLoadState(m_threadContext.core, 0, m_loadStateFlags);
|
mCoreLoadState(m_threadContext.core, 0, m_loadStateFlags);
|
||||||
|
@ -91,8 +81,10 @@ CoreController::CoreController(mCore* core, QObject* parent)
|
||||||
|
|
||||||
controller->m_resetActions.clear();
|
controller->m_resetActions.clear();
|
||||||
|
|
||||||
controller->m_activeBuffer = &controller->m_buffers[0];
|
if (!controller->m_hwaccel) {
|
||||||
context->core->setVideoBuffer(context->core, reinterpret_cast<color_t*>(controller->m_activeBuffer->data()), controller->screenDimensions().width());
|
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();
|
controller->finishFrame();
|
||||||
};
|
};
|
||||||
|
@ -211,6 +203,9 @@ CoreController::~CoreController() {
|
||||||
|
|
||||||
const color_t* CoreController::drawContext() {
|
const color_t* CoreController::drawContext() {
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
|
if (m_hwaccel) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
return reinterpret_cast<const color_t*>(m_completeBuffer.constData());
|
return reinterpret_cast<const color_t*>(m_completeBuffer.constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,6 +335,18 @@ void CoreController::setLogger(LogController* logger) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreController::start() {
|
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) {
|
if (!m_patched) {
|
||||||
mCoreAutoloadPatch(m_threadContext.core);
|
mCoreAutoloadPatch(m_threadContext.core);
|
||||||
}
|
}
|
||||||
|
@ -800,6 +807,16 @@ void CoreController::endVideoLog() {
|
||||||
m_vl = nullptr;
|
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() {
|
void CoreController::updateKeys() {
|
||||||
int activeKeys = m_activeKeys | updateAutofire() | m_inputController->pollEvents();
|
int activeKeys = m_activeKeys | updateAutofire() | m_inputController->pollEvents();
|
||||||
m_threadContext.core->setKeys(m_threadContext.core, activeKeys);
|
m_threadContext.core->setKeys(m_threadContext.core, activeKeys);
|
||||||
|
@ -823,17 +840,18 @@ int CoreController::updateAutofire() {
|
||||||
|
|
||||||
void CoreController::finishFrame() {
|
void CoreController::finishFrame() {
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
memcpy(m_completeBuffer.data(), m_activeBuffer->constData(), m_activeBuffer->size());
|
if (!m_hwaccel) {
|
||||||
|
memcpy(m_completeBuffer.data(), m_activeBuffer->constData(), m_activeBuffer->size());
|
||||||
|
|
||||||
// TODO: Generalize this to triple buffering?
|
// TODO: Generalize this to triple buffering?
|
||||||
m_activeBuffer = &m_buffers[0];
|
m_activeBuffer = &m_buffers[0];
|
||||||
if (m_activeBuffer == m_completeBuffer) {
|
if (m_activeBuffer == m_completeBuffer) {
|
||||||
m_activeBuffer = &m_buffers[1];
|
m_activeBuffer = &m_buffers[1];
|
||||||
|
}
|
||||||
|
// 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());
|
||||||
}
|
}
|
||||||
// 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) {
|
for (auto& action : m_frameActions) {
|
||||||
action();
|
action();
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,10 @@ public:
|
||||||
static const bool VIDEO_SYNC = false;
|
static const bool VIDEO_SYNC = false;
|
||||||
static const bool AUDIO_SYNC = true;
|
static const bool AUDIO_SYNC = true;
|
||||||
|
|
||||||
|
enum class Feature {
|
||||||
|
OPENGL = mCORE_FEATURE_OPENGL,
|
||||||
|
};
|
||||||
|
|
||||||
class Interrupter {
|
class Interrupter {
|
||||||
public:
|
public:
|
||||||
Interrupter(CoreController*, bool fromThread = false);
|
Interrupter(CoreController*, bool fromThread = false);
|
||||||
|
@ -69,6 +73,8 @@ public:
|
||||||
|
|
||||||
mPlatform platform() const;
|
mPlatform platform() const;
|
||||||
QSize screenDimensions() 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*);
|
void loadConfig(ConfigController*);
|
||||||
|
|
||||||
|
@ -154,6 +160,8 @@ public slots:
|
||||||
void startVideoLog(const QString& path);
|
void startVideoLog(const QString& path);
|
||||||
void endVideoLog();
|
void endVideoLog();
|
||||||
|
|
||||||
|
void setFramebufferHandle(int fb);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void started();
|
void started();
|
||||||
void paused();
|
void paused();
|
||||||
|
@ -188,6 +196,7 @@ private:
|
||||||
QByteArray m_buffers[2];
|
QByteArray m_buffers[2];
|
||||||
QByteArray* m_activeBuffer;
|
QByteArray* m_activeBuffer;
|
||||||
QByteArray m_completeBuffer;
|
QByteArray m_completeBuffer;
|
||||||
|
bool m_hwaccel = false;
|
||||||
|
|
||||||
std::unique_ptr<mCacheSet> m_cacheSet;
|
std::unique_ptr<mCacheSet> m_cacheSet;
|
||||||
std::unique_ptr<Override> m_override;
|
std::unique_ptr<Override> m_override;
|
||||||
|
|
|
@ -49,6 +49,7 @@ public:
|
||||||
virtual bool supportsShaders() const = 0;
|
virtual bool supportsShaders() const = 0;
|
||||||
virtual VideoShader* shaders() = 0;
|
virtual VideoShader* shaders() = 0;
|
||||||
virtual VideoProxy* videoProxy() { return nullptr; }
|
virtual VideoProxy* videoProxy() { return nullptr; }
|
||||||
|
virtual int framebufferHandle() { return -1; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void showCursor();
|
void showCursor();
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#ifdef BUILD_GL
|
#ifdef BUILD_GL
|
||||||
#include "platform/opengl/gl.h"
|
#include "platform/opengl/gl.h"
|
||||||
#endif
|
#endif
|
||||||
#if !defined(_WIN32) || defined(USE_EPOXY)
|
#ifdef BUILD_GLES2
|
||||||
#include "platform/opengl/gles2.h"
|
#include "platform/opengl/gles2.h"
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <epoxy/wgl.h>
|
#include <epoxy/wgl.h>
|
||||||
|
@ -195,6 +195,10 @@ VideoProxy* DisplayGL::videoProxy() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DisplayGL::framebufferHandle() {
|
||||||
|
return m_painter->glTex();
|
||||||
|
}
|
||||||
|
|
||||||
PainterGL::PainterGL(int majorVersion, VideoProxy* proxy, QGLWidget* parent)
|
PainterGL::PainterGL(int majorVersion, VideoProxy* proxy, QGLWidget* parent)
|
||||||
: m_gl(parent)
|
: m_gl(parent)
|
||||||
, m_videoProxy(proxy)
|
, m_videoProxy(proxy)
|
||||||
|
@ -202,7 +206,7 @@ PainterGL::PainterGL(int majorVersion, VideoProxy* proxy, QGLWidget* parent)
|
||||||
#ifdef BUILD_GL
|
#ifdef BUILD_GL
|
||||||
mGLContext* glBackend;
|
mGLContext* glBackend;
|
||||||
#endif
|
#endif
|
||||||
#if !defined(_WIN32) || defined(USE_EPOXY)
|
#ifdef BUILD_GLES2
|
||||||
mGLES2Context* gl2Backend;
|
mGLES2Context* gl2Backend;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -213,7 +217,7 @@ PainterGL::PainterGL(int majorVersion, VideoProxy* proxy, QGLWidget* parent)
|
||||||
|
|
||||||
QStringList extensions = QString(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))).split(' ');
|
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) {
|
if (extensions.contains("GL_ARB_framebuffer_object") && majorVersion >= 2) {
|
||||||
gl2Backend = static_cast<mGLES2Context*>(malloc(sizeof(mGLES2Context)));
|
gl2Backend = static_cast<mGLES2Context*>(malloc(sizeof(mGLES2Context)));
|
||||||
mGLES2ContextCreate(gl2Backend);
|
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()));
|
m_backend->init(m_backend, reinterpret_cast<WHandle>(m_gl->winId()));
|
||||||
#if !defined(_WIN32) || defined(USE_EPOXY)
|
#ifdef BUILD_GLES2
|
||||||
if (m_supportsShaders) {
|
if (m_supportsShaders) {
|
||||||
m_shader.preprocessShader = static_cast<void*>(&reinterpret_cast<mGLES2Context*>(m_backend)->initialShader);
|
m_shader.preprocessShader = static_cast<void*>(&reinterpret_cast<mGLES2Context*>(m_backend)->initialShader);
|
||||||
}
|
}
|
||||||
|
@ -266,7 +270,7 @@ PainterGL::~PainterGL() {
|
||||||
#if defined(_WIN32) && defined(USE_EPOXY)
|
#if defined(_WIN32) && defined(USE_EPOXY)
|
||||||
epoxy_handle_external_wglMakeCurrent();
|
epoxy_handle_external_wglMakeCurrent();
|
||||||
#endif
|
#endif
|
||||||
#if !defined(_WIN32) || defined(USE_EPOXY)
|
#ifdef BUILD_GLES2
|
||||||
if (m_shader.passes) {
|
if (m_shader.passes) {
|
||||||
mGLES2ShaderFree(&m_shader);
|
mGLES2ShaderFree(&m_shader);
|
||||||
}
|
}
|
||||||
|
@ -339,7 +343,7 @@ void PainterGL::start() {
|
||||||
epoxy_handle_external_wglMakeCurrent();
|
epoxy_handle_external_wglMakeCurrent();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(_WIN32) || defined(USE_EPOXY)
|
#ifdef BUILD_GLES2
|
||||||
if (m_supportsShaders && m_shader.passes) {
|
if (m_supportsShaders && m_shader.passes) {
|
||||||
mGLES2ShaderAttach(reinterpret_cast<mGLES2Context*>(m_backend), static_cast<mGLES2Shader*>(m_shader.passes), m_shader.nPasses);
|
mGLES2ShaderAttach(reinterpret_cast<mGLES2Context*>(m_backend), static_cast<mGLES2Shader*>(m_shader.passes), m_shader.nPasses);
|
||||||
}
|
}
|
||||||
|
@ -422,14 +426,16 @@ void PainterGL::performDraw() {
|
||||||
|
|
||||||
void PainterGL::enqueue(const uint32_t* backing) {
|
void PainterGL::enqueue(const uint32_t* backing) {
|
||||||
m_mutex.lock();
|
m_mutex.lock();
|
||||||
uint32_t* buffer;
|
uint32_t* buffer = nullptr;
|
||||||
if (m_free.isEmpty()) {
|
if (backing) {
|
||||||
buffer = m_queue.dequeue();
|
if (m_free.isEmpty()) {
|
||||||
} else {
|
buffer = m_queue.dequeue();
|
||||||
buffer = m_free.takeLast();
|
} else {
|
||||||
|
buffer = m_free.takeLast();
|
||||||
|
}
|
||||||
|
QSize size = m_context->screenDimensions();
|
||||||
|
memcpy(buffer, backing, size.width() * size.height() * BYTES_PER_PIXEL);
|
||||||
}
|
}
|
||||||
QSize size = m_context->screenDimensions();
|
|
||||||
memcpy(buffer, backing, size.width() * size.height() * BYTES_PER_PIXEL);
|
|
||||||
m_queue.enqueue(buffer);
|
m_queue.enqueue(buffer);
|
||||||
m_mutex.unlock();
|
m_mutex.unlock();
|
||||||
}
|
}
|
||||||
|
@ -441,8 +447,10 @@ void PainterGL::dequeue() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint32_t* buffer = m_queue.dequeue();
|
uint32_t* buffer = m_queue.dequeue();
|
||||||
m_backend->postFrame(m_backend, buffer);
|
if (buffer) {
|
||||||
m_free.append(buffer);
|
m_backend->postFrame(m_backend, buffer);
|
||||||
|
m_free.append(buffer);
|
||||||
|
}
|
||||||
m_mutex.unlock();
|
m_mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,7 +459,9 @@ void PainterGL::dequeueAll() {
|
||||||
m_mutex.lock();
|
m_mutex.lock();
|
||||||
while (!m_queue.isEmpty()) {
|
while (!m_queue.isEmpty()) {
|
||||||
buffer = m_queue.dequeue();
|
buffer = m_queue.dequeue();
|
||||||
m_free.append(buffer);
|
if (buffer) {
|
||||||
|
m_free.append(buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (buffer) {
|
if (buffer) {
|
||||||
m_backend->postFrame(m_backend, buffer);
|
m_backend->postFrame(m_backend, buffer);
|
||||||
|
@ -464,7 +474,7 @@ void PainterGL::setShaders(struct VDir* dir) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!m_active) {
|
if (!m_active) {
|
||||||
#if !defined(_WIN32) || defined(USE_EPOXY)
|
#ifdef BUILD_GLES2
|
||||||
m_gl->makeCurrent();
|
m_gl->makeCurrent();
|
||||||
#if defined(_WIN32) && defined(USE_EPOXY)
|
#if defined(_WIN32) && defined(USE_EPOXY)
|
||||||
epoxy_handle_external_wglMakeCurrent();
|
epoxy_handle_external_wglMakeCurrent();
|
||||||
|
@ -489,7 +499,7 @@ void PainterGL::clearShaders() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!m_active) {
|
if (!m_active) {
|
||||||
#if !defined(_WIN32) || defined(USE_EPOXY)
|
#ifdef BUILD_GLES2
|
||||||
m_gl->makeCurrent();
|
m_gl->makeCurrent();
|
||||||
#if defined(_WIN32) && defined(USE_EPOXY)
|
#if defined(_WIN32) && defined(USE_EPOXY)
|
||||||
epoxy_handle_external_wglMakeCurrent();
|
epoxy_handle_external_wglMakeCurrent();
|
||||||
|
@ -509,4 +519,19 @@ VideoShader* PainterGL::shaders() {
|
||||||
return &m_shader;
|
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
|
#endif
|
||||||
|
|
|
@ -52,6 +52,7 @@ public:
|
||||||
bool supportsShaders() const override;
|
bool supportsShaders() const override;
|
||||||
VideoShader* shaders() override;
|
VideoShader* shaders() override;
|
||||||
VideoProxy* videoProxy() override;
|
VideoProxy* videoProxy() override;
|
||||||
|
int framebufferHandle() override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void stopDrawing() override;
|
void stopDrawing() override;
|
||||||
|
@ -111,6 +112,8 @@ public slots:
|
||||||
void clearShaders();
|
void clearShaders();
|
||||||
VideoShader* shaders();
|
VideoShader* shaders();
|
||||||
|
|
||||||
|
int glTex();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void performDraw();
|
void performDraw();
|
||||||
void dequeue();
|
void dequeue();
|
||||||
|
|
|
@ -851,6 +851,10 @@ void Window::unimplementedBiosCall(int call) {
|
||||||
|
|
||||||
void Window::reloadDisplayDriver() {
|
void Window::reloadDisplayDriver() {
|
||||||
if (m_controller) {
|
if (m_controller) {
|
||||||
|
if (m_controller->hardwareAccelerated()) {
|
||||||
|
mustRestart();
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_display->stopDrawing();
|
m_display->stopDrawing();
|
||||||
detachWidget(m_display.get());
|
detachWidget(m_display.get());
|
||||||
}
|
}
|
||||||
|
@ -1715,8 +1719,15 @@ void Window::setController(CoreController* controller, const QString& fname) {
|
||||||
reloadDisplayDriver();
|
reloadDisplayDriver();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_display->videoProxy()) {
|
if (m_config->getOption("hwaccelVideo").toInt() && m_display->supportsShaders() && controller->supportsFeature(CoreController::Feature::OPENGL)) {
|
||||||
m_display->videoProxy()->attach(controller);
|
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_controller = std::shared_ptr<CoreController>(controller);
|
||||||
|
|
|
@ -77,12 +77,11 @@ if(BUILD_PANDORA)
|
||||||
else()
|
else()
|
||||||
if(BUILD_GL)
|
if(BUILD_GL)
|
||||||
list(APPEND MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/gl-sdl.c)
|
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)
|
list(APPEND PLATFORM_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/gl-common.c)
|
||||||
include_directories(${OPENGL_INCLUDE_DIR})
|
|
||||||
endif()
|
endif()
|
||||||
if(BUILD_GLES2)
|
if(BUILD_GLES2)
|
||||||
list(APPEND MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/gles2-sdl.c)
|
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})
|
include_directories(${OPENGLES2_INCLUDE_DIR})
|
||||||
endif()
|
endif()
|
||||||
if(NOT BUILD_GL AND NOT BUILD_GLES2)
|
if(NOT BUILD_GL AND NOT BUILD_GLES2)
|
||||||
|
|
|
@ -35,7 +35,9 @@ bool mSDLGLES2Init(struct mSDLRenderer* renderer) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
size_t size = renderer->width * renderer->height * BYTES_PER_PIXEL;
|
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);
|
renderer->outputBuffer = memalign(16, size);
|
||||||
#else
|
#else
|
||||||
posix_memalign((void**) &renderer->outputBuffer, 16, size);
|
posix_memalign((void**) &renderer->outputBuffer, 16, size);
|
||||||
|
|
|
@ -31,6 +31,7 @@ while [ $# -gt 0 ]; do
|
||||||
rmdep libav
|
rmdep libav
|
||||||
rmdep libedit
|
rmdep libedit
|
||||||
rmdep libelf
|
rmdep libelf
|
||||||
|
rmdep libgl
|
||||||
rmdep libpng
|
rmdep libpng
|
||||||
rmdep libzip
|
rmdep libzip
|
||||||
rmdep libmagickwand
|
rmdep libmagickwand
|
||||||
|
@ -45,6 +46,7 @@ while [ $# -gt 0 ]; do
|
||||||
rmdep libav
|
rmdep libav
|
||||||
rmdep libedit
|
rmdep libedit
|
||||||
rmdep libelf
|
rmdep libelf
|
||||||
|
rmdep libgl
|
||||||
rmdep libpng
|
rmdep libpng
|
||||||
rmdep qt
|
rmdep qt
|
||||||
rmdep libzip
|
rmdep libzip
|
||||||
|
|
Loading…
Reference in New Issue