diff --git a/desmume/src/Makefile.am b/desmume/src/Makefile.am index b17d4df7f..971611eea 100644 --- a/desmume/src/Makefile.am +++ b/desmume/src/Makefile.am @@ -29,7 +29,6 @@ libdesmume_a_SOURCES = \ wifi.cpp wifi.h \ mic.h \ MMU.cpp MMU.h MMU_timing.h NDSSystem.cpp NDSSystem.h registers.h \ - OGLRender.h OGLRender_3_2.h \ ROMReader.cpp ROMReader.h \ render3D.cpp render3D.h \ rtc.cpp rtc.h \ @@ -230,8 +229,17 @@ libdesmume_a_SOURCES += \ utils/AsmJit/x86/x86util.h endif -if HAVE_GL -libdesmume_a_SOURCES += OGLRender.cpp OGLRender_3_2.cpp +if ENABLE_OPENGL_ES +libdesmume_a_SOURCES += \ + OGLRender.h OGLRender_3_2.h \ + OGLRender.cpp OGLRender_3_2.cpp \ + OGLRender_ES3.h OGLRender_ES3.cpp +else +if ENABLE_OPENGL_STANDARD +libdesmume_a_SOURCES += \ + OGLRender.h OGLRender_3_2.h \ + OGLRender.cpp OGLRender_3_2.cpp +endif endif if HAVE_OPENAL diff --git a/desmume/src/OGLRender.h b/desmume/src/OGLRender.h index ffdd160bb..4c207ea47 100644 --- a/desmume/src/OGLRender.h +++ b/desmume/src/OGLRender.h @@ -27,29 +27,15 @@ #include "render3D.h" #include "types.h" -// OPENGL PLATFORM-SPECIFIC INCLUDES -#if defined(__ANGLE__) || defined(__ANDROID__) - #define OPENGL_VARIANT_ES - #define _NO_SDL_TYPES - #include - #define __gles2_gl2_h_ // Guard against including the gl2.h file. - #include // "gl3ext.h" is just a stub file. The real extension header is "gl2ext.h". +// The macros ENABLE_OPENGL_STANDARD and ENABLE_OPENGL_ES are used in client build configs. +// If a client wants to use OpenGL, they must declare one of these two macros somewhere in +// their build config or declare it in some precompiled header. - // Ignore dynamic linking - #define OGLEXT(procPtr, func) - #define INITOGLEXT(procPtr, func) - #define EXTERNOGLEXT(procPtr, func) -#elif defined(__EMSCRIPTEN__) - #define OPENGL_VARIANT_ES - #include - #include - - // Ignore dynamic linking - #define OGLEXT(procPtr, func) - #define INITOGLEXT(procPtr, func) - #define EXTERNOGLEXT(procPtr, func) -#elif defined(_WIN32) - #define OPENGL_VARIANT_STANDARD +// OPENGL PLATFORM-SPECIFIC INCLUDES +#if defined(_WIN32) + #ifndef ENABLE_OPENGL_STANDARD + #define ENABLE_OPENGL_STANDARD // TODO: Declare this in the Visual Studio project file. + #endif #define WIN32_LEAN_AND_MEAN #include #include @@ -63,15 +49,10 @@ #define INITOGLEXT(procPtr, func) func = (procPtr)wglGetProcAddress(#func); #define EXTERNOGLEXT(procPtr, func) extern procPtr func; #elif defined(__APPLE__) - #include - - #if TARGET_OS_IPHONE - #define OPENGL_VARIANT_ES + #if defined(ENABLE_OPENGL_ES) #include #include - #else - #define OPENGL_VARIANT_STANDARD - + #elif defined(ENABLE_OPENGL_STANDARD) #ifdef OGLRENDER_3_2_H #include #include @@ -93,36 +74,46 @@ #define INITOGLEXT(procPtr, func) #define EXTERNOGLEXT(procPtr, func) #else - #define OPENGL_VARIANT_STANDARD - #include - #include - #include + #if defined(ENABLE_OPENGL_ES) + #include + #define __gles2_gl2_h_ // Guard against including the gl2.h file. + #include // "gl3ext.h" is just a stub file. The real extension header is "gl2ext.h". + + // Ignore dynamic linking + #define OGLEXT(procPtr, func) + #define INITOGLEXT(procPtr, func) + #define EXTERNOGLEXT(procPtr, func) + #elif defined(ENABLE_OPENGL_STANDARD) + #include + #include + #include - #ifdef OGLRENDER_3_2_H - #include "utils/glcorearb.h" - #else - /* This is a workaround needed to compile against nvidia GL headers */ - #ifndef GL_ALPHA_BLEND_EQUATION_ATI - #undef GL_VERSION_1_3 + #ifdef OGLRENDER_3_2_H + #include "utils/glcorearb.h" + #else + // This is a workaround needed to compile against nvidia GL headers + #ifndef GL_ALPHA_BLEND_EQUATION_ATI + #undef GL_VERSION_1_3 + #endif #endif - #endif - #define OGLEXT(procPtr, func) procPtr func = NULL; - #define INITOGLEXT(procPtr, func) func = (procPtr)glXGetProcAddress((const GLubyte *) #func); - #define EXTERNOGLEXT(procPtr, func) extern procPtr func; + #define OGLEXT(procPtr, func) procPtr func = NULL; + #define INITOGLEXT(procPtr, func) func = (procPtr)glXGetProcAddress((const GLubyte *) #func); + #define EXTERNOGLEXT(procPtr, func) extern procPtr func; + #endif #endif // Check minimum OpenGL header version -#if defined(OPENGL_VARIANT_STANDARD) - #if !defined(GL_VERSION_2_1) - #error OpenGL requires v2.1 headers or later. - #endif -#elif defined(OPENGL_VARIANT_ES) +#if defined(ENABLE_OPENGL_ES) #if !defined(GL_ES_VERSION_3_0) #error OpenGL ES requires v3.0 headers or later. #endif +#elif defined(ENABLE_OPENGL_STANDARD) + #if !defined(GL_VERSION_2_1) + #error Standard OpenGL requires v2.1 headers or later. + #endif #else - #error Unknown OpenGL variant. + #error No OpenGL variant selected. You must declare ENABLE_OPENGL_STANDARD or ENABLE_OPENGL_ES in your build configuration. #endif // OPENGL LEGACY CORE FUNCTIONS diff --git a/desmume/src/frontend/cocoa/DeSmuME (Latest).xcodeproj/project.pbxproj b/desmume/src/frontend/cocoa/DeSmuME (Latest).xcodeproj/project.pbxproj index f1b964a5a..b674e6082 100755 --- a/desmume/src/frontend/cocoa/DeSmuME (Latest).xcodeproj/project.pbxproj +++ b/desmume/src/frontend/cocoa/DeSmuME (Latest).xcodeproj/project.pbxproj @@ -4416,6 +4416,8 @@ ABD2CE4426E05CB000FB15F7 /* DeSmuME (x86_64h).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "DeSmuME (x86_64h).app"; sourceTree = BUILT_PRODUCTS_DIR; }; ABD42045172319D1006A9B46 /* FileMigrationDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileMigrationDelegate.h; sourceTree = ""; }; ABD42046172319D1006A9B46 /* FileMigrationDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FileMigrationDelegate.mm; sourceTree = ""; }; + ABDD89EF2C30BE97003482B7 /* OGLRender_ES3.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OGLRender_ES3.h; sourceTree = ""; }; + ABDD89F02C30BE97003482B7 /* OGLRender_ES3.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = OGLRender_ES3.cpp; sourceTree = ""; }; ABDDF7C41898F024007583C1 /* Icon_DisplayToggle_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_DisplayToggle_420x420.png; path = images/Icon_DisplayToggle_420x420.png; sourceTree = ""; }; ABDDF7C71898F032007583C1 /* Icon_FrameAdvance_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_FrameAdvance_420x420.png; path = images/Icon_FrameAdvance_420x420.png; sourceTree = ""; }; ABDDF7C81898F032007583C1 /* Icon_FrameJump_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_FrameJump_420x420.png; path = images/Icon_FrameJump_420x420.png; sourceTree = ""; }; @@ -5692,6 +5694,7 @@ ABD1FEC01345AC8400AF11D1 /* NDSSystem.cpp */, ABD1FEC11345AC8400AF11D1 /* OGLRender.cpp */, AB68A0DA16B139BC00DE0546 /* OGLRender_3_2.cpp */, + ABDD89F02C30BE97003482B7 /* OGLRender_ES3.cpp */, ABD1FEC21345AC8400AF11D1 /* path.cpp */, ABD1FEC31345AC8400AF11D1 /* rasterize.cpp */, ABD1FEC41345AC8400AF11D1 /* readwrite.cpp */, @@ -5739,6 +5742,7 @@ ABD1FE8C1345AC8400AF11D1 /* NDSSystem.h */, ABD1FE8D1345AC8400AF11D1 /* OGLRender.h */, ABBB421516B4A5F30012E5AB /* OGLRender_3_2.h */, + ABDD89EF2C30BE97003482B7 /* OGLRender_ES3.h */, ABD1FE8F1345AC8400AF11D1 /* PACKED.h */, ABD1FE8E1345AC8400AF11D1 /* PACKED_END.h */, ABD1FE901345AC8400AF11D1 /* path.h */, diff --git a/desmume/src/frontend/cocoa/DeSmuME_Prefix.pch b/desmume/src/frontend/cocoa/DeSmuME_Prefix.pch index e7c124cec..d030561cc 100644 --- a/desmume/src/frontend/cocoa/DeSmuME_Prefix.pch +++ b/desmume/src/frontend/cocoa/DeSmuME_Prefix.pch @@ -1,6 +1,6 @@ /* Copyright (C) 2011 Roger Manuel - Copyright (C) 2012-2021 DeSmuME team + Copyright (C) 2012-2024 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,7 +22,7 @@ #define HOST_DARWIN #define DESMUME_COCOA -#define HAVE_OPENGL +#define ENABLE_OPENGL_STANDARD #define HAVE_LIBZ //#define HAVE_LUA //#define HAVE_AV_CONFIG_H diff --git a/desmume/src/frontend/cocoa/openemu/DeSmuME_Prefix_OpenEmu.pch b/desmume/src/frontend/cocoa/openemu/DeSmuME_Prefix_OpenEmu.pch index 4dd987aa6..0252bfd9b 100644 --- a/desmume/src/frontend/cocoa/openemu/DeSmuME_Prefix_OpenEmu.pch +++ b/desmume/src/frontend/cocoa/openemu/DeSmuME_Prefix_OpenEmu.pch @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2022 DeSmuME team + Copyright (C) 2012-2024 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,7 +21,7 @@ #define HOST_DARWIN #define DESMUME_COCOA -#define HAVE_OPENGL +#define ENABLE_OPENGL_STANDARD #define HAVE_LIBZ #define FT2_BUILD_LIBRARY diff --git a/desmume/src/frontend/modules/ImageOut.cpp b/desmume/src/frontend/modules/ImageOut.cpp index f7c5e56df..d0b5e6511 100644 --- a/desmume/src/frontend/modules/ImageOut.cpp +++ b/desmume/src/frontend/modules/ImageOut.cpp @@ -23,7 +23,7 @@ #include "formats/rbmp.h" #include "GPU.h" -static u8* Convert15To24(const u16* src, int width, int height) +u8* Convert15To24(const u16* src, int width, int height) { u8 *tmp_buffer; u8 *tmp_inc; @@ -66,4 +66,4 @@ int NDS_WriteBMP_32bppBuffer(int width, int height, const void* buf, const char { bool ok = rbmp_save_image(filename,buf,width,height,width*4,(rbmp_source_type)(RBMP_SOURCE_TYPE_ARGB8888 | RBMP_SOURCE_TYPE_YFLIPPED)); return ok?1:0; -} \ No newline at end of file +} diff --git a/desmume/src/frontend/posix/Makefile.am b/desmume/src/frontend/posix/Makefile.am index 4329a89e7..7da01eb2f 100644 --- a/desmume/src/frontend/posix/Makefile.am +++ b/desmume/src/frontend/posix/Makefile.am @@ -38,7 +38,6 @@ libdesmume_a_SOURCES = \ ../../wifi.cpp ../../wifi.h \ ../../mic.h \ ../../MMU.cpp ../../MMU.h ../../MMU_timing.h ../../NDSSystem.cpp ../../NDSSystem.h ../../registers.h \ - ../../OGLRender.h ../../OGLRender_3_2.h \ ../../ROMReader.cpp ../../ROMReader.h \ ../../render3D.cpp ../../render3D.h \ ../../rtc.cpp ../../rtc.h \ @@ -211,8 +210,17 @@ endif libdesmume_a_SOURCES += shared/desmume_config.cpp shared/desmume_config.h -if HAVE_GL -libdesmume_a_SOURCES += ../../OGLRender.cpp ../../OGLRender_3_2.cpp +if ENABLE_OPENGL_ES +libdesmume_a_SOURCES += \ + ../../OGLRender.h ../../OGLRender_3_2.h \ + ../../OGLRender.cpp ../../OGLRender_3_2.cpp \ + ../../OGLRender_ES3.h ../../OGLRender_ES3.cpp +else +if ENABLE_OPENGL_STANDARD +libdesmume_a_SOURCES += \ + ../../OGLRender.h ../../OGLRender_3_2.h \ + ../../OGLRender.cpp ../../OGLRender_3_2.cpp +endif endif if HAVE_OPENAL diff --git a/desmume/src/frontend/posix/codeblocks/desmume.cbp b/desmume/src/frontend/posix/codeblocks/desmume.cbp new file mode 100644 index 000000000..120d59b08 --- /dev/null +++ b/desmume/src/frontend/posix/codeblocks/desmume.cbp @@ -0,0 +1,1348 @@ + + + + + + diff --git a/desmume/src/frontend/posix/configure.ac b/desmume/src/frontend/posix/configure.ac index 7b92781e3..89b886618 100644 --- a/desmume/src/frontend/posix/configure.ac +++ b/desmume/src/frontend/posix/configure.ac @@ -70,32 +70,139 @@ else AC_MSG_ERROR([sdl is required to build desmume]) fi -dnl - Check for the OpenGL includes -AC_CHECK_HEADERS([GL/gl.h], - [AC_CHECK_HEADERS([GL/glu.h], [have_gl_h=yes LIBS="$LIBS -lGL -lGLU"], [have_gl_h=no])], - [have_gl_h=no]) -if test "have_gl_h" = "no" ; then - AC_MSG_WARN([Building without GL support because of missing headers.]) +dnl - if --enable-opengl is used, check for it +AC_ARG_ENABLE([opengl], + [AC_HELP_STRING([--enable-opengl], [Build for standard OpenGL])], + [opengl=$enableval], + [opengl=no]) + +if test "x$opengl" = "xyes" ; then + AC_CHECK_HEADERS([GL/gl.h], + [AC_CHECK_HEADERS([GL/glcorearb.h], [have_opengl=yes], [have_opengl=no])], + [have_opengl=no]) + if test "have_opengl" = "no" ; then + AC_MSG_WARN([Cannot build with OpenGL -- headers not found.]) + else + AC_CHECK_LIB(dl, main) + AC_CHECK_LIB(GL, main,[ + AC_DEFINE([ENABLE_OPENGL_STANDARD]) + OPENGL_LIBS="-lGL" + AC_SUBST(OPENGL_LIBS) + ]) + fi fi -AM_CONDITIONAL([HAVE_GL], [test "${have_gl_h}" = "yes"]) +AM_CONDITIONAL([ENABLE_OPENGL_STANDARD], [test "${have_opengl}" = "yes"]) + +dnl - if --enable-opengles is used, check for it +AC_ARG_ENABLE([opengles], + [AC_HELP_STRING([--enable-opengles], [Build for OpenGL ES, overrides --enable-opengl])], + [opengles=$enableval], + [opengles=no]) + +if test "x$opengles" = "xyes" ; then + AC_CHECK_HEADERS([GLES3/gl3.h], + [AC_CHECK_HEADERS([GLES3/gl3ext.h], [have_opengles=yes], [have_opengles=no])], + [have_opengles=no]) + if test "have_opengles" = "no" ; then + AC_MSG_WARN([Cannot build with OpenGL ES -- headers not found.]) + else + AC_CHECK_LIB(dl, main) + AC_CHECK_LIB(GLESv2, main,[ + AC_DEFINE([ENABLE_OPENGL_ES]) + OPENGLES_LIBS="-lGLESv2" + AC_SUBST(OPENGLES_LIBS) + ]) + fi +fi +AM_CONDITIONAL([ENABLE_OPENGL_ES], [test "${have_opengles}" = "yes"]) + +dnl - if --enable-glx is used, check for it +AC_ARG_ENABLE([glx], + [AC_HELP_STRING([--enable-glx], [Use a GLX context, overrides --enable-osmesa and --enable-egl])], + [glx=$enableval], + [glx=no]) + +if test "x$glx" = "xyes" ; then + AC_CHECK_HEADERS([GL/glx.h], [have_glx=yes], [have_glx=no]) + if test "have_glx" = "no" ; then + AC_MSG_WARN([Cannot use GLX -- headers not found.]) + else + AC_CHECK_LIB(dl, main) + AC_CHECK_LIB(GL, main) + AC_CHECK_LIB(GLX, main) + fi +fi + +if test "$have_glx" = "yes" ; then + if test "$have_opengl" = "yes" ; then + AC_DEFINE(ENABLE_GLX) + GLX_LIBS="-lGLX" + AC_SUBST(GLX_LIBS) + else + have_glx=no + if test "$have_opengles" = "yes" ; then + AC_MSG_WARN([GLX contexts are incompatible with OpenGL ES -- cancelling the use of GLX.]) + else + AC_MSG_WARN([GLX contexts are only compatible with standard OpenGL -- cancelling the use of GLX.]) + fi + fi +fi +AM_CONDITIONAL([ENABLE_GLX], [test "${have_glx}" = "yes"]) dnl - if --enable-osmesa is used, check for it AC_ARG_ENABLE([osmesa], - [AC_HELP_STRING([--enable-osmesa], [use off-screen mesa])], + [AC_HELP_STRING([--enable-osmesa], [Use an OSMesa context, overrides --enable-egl])], [osmesa=$enableval], [osmesa=no]) if test "x$osmesa" = "xyes" ; then - AC_CHECK_LIB(dl, main) - AC_CHECK_LIB([GL], main) - AC_CHECK_LIB(OSMesa, main,[ - useosmesa=yes - AC_DEFINE(HAVE_LIBOSMESA) - OSMESA_LIBS="-lOSMesa" + AC_CHECK_HEADERS([GL/osmesa.h], [have_osmesa=yes], [have_osmesa=no]) + if test "have_osmesa" = "no" ; then + AC_MSG_WARN([Cannot use OSMesa -- headers not found.]) + else + AC_MSG_WARN([OSMesa contexts are deprecated.]) + AC_CHECK_LIB(dl, main) + AC_CHECK_LIB(GL, main) + AC_CHECK_LIB(OSMesa, main) + fi +fi + +if test "$have_osmesa" = "yes" ; then + if test "$have_opengl" = "yes" ; then + AC_DEFINE(ENABLE_OSMESA) + OSMESA_LIBS="-lOSMesa" AC_SUBST(OSMESA_LIBS) - ]) + else + have_osmesa=no + if test "$have_opengles" = "yes" ; then + AC_MSG_WARN([OSMesa contexts are incompatible with OpenGL ES -- cancelling the use of OSMesa.]) + else + AC_MSG_WARN([OSMesa contexts are only compatible with standard OpenGL -- cancelling the use of OSMesa.]) + fi + fi +fi +AM_CONDITIONAL([ENABLE_OSMESA], [test "${have_osmesa}" = "yes"]) + +dnl - if --enable-egl is used, check for it +AC_ARG_ENABLE([egl], + [AC_HELP_STRING([--enable-egl], [Use an EGL context])], + [egl=$enableval], + [egl=no]) + +if test "x$egl" = "xyes" ; then + AC_CHECK_HEADERS([EGL/egl.h], [have_egl=yes], [have_egl=no]) + if test "have_egl" = "no" ; then + AC_MSG_WARN([Cannot use EGL -- headers not found.]) + else + AC_CHECK_LIB(dl, main) + AC_CHECK_LIB(EGL, main,[ + AC_DEFINE(ENABLE_EGL) + EGL_LIBS="-lEGL" + AC_SUBST(EGL_LIBS) + ]) + fi fi -AM_CONDITIONAL([HAVE_LIBOSMESA], [test "${useosmesa}" = "yes"]) +AM_CONDITIONAL([ENABLE_EGL], [test "${have_egl}" = "yes"]) dnl - make the usage of libagg for HUD rendering configurable AC_ARG_ENABLE([hud], diff --git a/desmume/src/frontend/posix/gtk/Makefile.am b/desmume/src/frontend/posix/gtk/Makefile.am index b38012cde..c4952a715 100644 --- a/desmume/src/frontend/posix/gtk/Makefile.am +++ b/desmume/src/frontend/posix/gtk/Makefile.am @@ -9,26 +9,47 @@ pixmapdir = $(datadir)/pixmaps pixmap_DATA = DeSmuME.svg EXTRA_DIST = DeSmuME.svg desmume.desktop bin_PROGRAMS = desmume + desmume_SOURCES = \ - avout.h \ - avout_pipe_base.cpp avout_pipe_base.h \ - avout_x264.cpp avout_x264.h \ - avout_flac.cpp avout_flac.h \ + ../shared/avout.h \ + ../shared/avout_flac.h ../shared/avout_flac.cpp \ + ../shared/avout_pipe_base.h ../shared/avout_pipe_base.cpp \ + ../shared/avout_x264.h ../shared/avout_x264.cpp \ + ../shared/ctrlssdl.h ../shared/ctrlssdl.cpp \ + ../shared/sndsdl.cpp \ config.cpp config.h config_opts.h \ desmume.h desmume.cpp \ dTool.h dToolsList.cpp \ tools/ioregsView.cpp tools/ioregsView.h \ - ../shared/sndsdl.cpp \ - ../shared/ctrlssdl.h ../shared/ctrlssdl.cpp \ - osmesa_3Demu.cpp osmesa_3Demu.h \ - sdl_3Demu.cpp sdl_3Demu.h \ cheatsGTK.h cheatsGTK.cpp \ main.cpp main.h + desmume_LDADD = ../libdesmume.a \ $(X_LIBS) -lX11 $(SDL_LIBS) $(GTK_LIBS) $(GTHREAD_LIBS) $(ALSA_LIBS) $(LIBAGG_LIBS) $(LIBSOUNDTOUCH_LIBS) -if HAVE_LIBOSMESA + +if ENABLE_OPENGL_ES +desmume_LDADD += $(OPENGLES_LIBS) +else +if ENABLE_OPENGL_STANDARD +desmume_LDADD += $(OPENGL_LIBS) +endif +endif + +if ENABLE_GLX +desmume_LDADD += $(GLX_LIBS) +desmume_SOURCES += ../shared/glx_3Demu.h ../shared/glx_3Demu.cpp +else +if ENABLE_OSMESA desmume_LDADD += $(OSMESA_LIBS) +desmume_SOURCES += ../shared/osmesa_3Demu.h ../shared/osmesa_3Demu.cpp else +if ENABLE_EGL +desmume_LDADD += $(EGL_LIBS) +desmume_SOURCES += ../shared/egl_3Demu.h ../shared/egl_3Demu.cpp +else +desmume_SOURCES += ../shared/sdl_3Demu.h ../shared/sdl_3Demu.cpp +endif +endif endif UPDATE_DESKTOP = \ @@ -43,4 +64,4 @@ install-data-hook: $(UPDATE_DESKTOP) uninstall-hook: - $(UPDATE_DESKTOP) + $(UPDATE_DESKTOP) diff --git a/desmume/src/frontend/posix/gtk/graphics.ui b/desmume/src/frontend/posix/gtk/graphics.ui index f8dc2976b..8134782c7 100644 --- a/desmume/src/frontend/posix/gtk/graphics.ui +++ b/desmume/src/frontend/posix/gtk/graphics.ui @@ -1,4 +1,5 @@ + @@ -49,40 +50,49 @@ + + False + False 3D Core: - 0 - 0 + 0 + 0 + False Null SoftRasterizer - OpenGL + OpenGL (Auto) + OpenGL (Legacy) + OpenGL 3.2 + OpenGL ES 3.0 - 1 - 0 + 1 + 0 + False 3D Texture Upscaling: - 0 - 1 + 0 + 1 + False ×1 ×2 @@ -90,70 +100,79 @@ - 1 - 1 + 1 + 1 + False GPU scale factor: - 0 - 2 + 0 + 2 - true - 0 + False + True - 1 - 2 + 1 + 2 3D Texture Deposterization + False + False True - 0 - 3 + 0 + 3 3D Texture Smoothing + False + False True - 0 - 4 + 0 + 4 High Resolution Color Interpolation (SoftRasterizer) + False + False True - 1 - 4 + 1 + 4 + False Multisample Antialiasing (OpenGL): - 0 - 5 + 0 + 5 + False None 2 @@ -164,11 +183,37 @@ - 1 - 5 + 1 + 5 + + + + + + + + + + + + + + + + + + + + + + + False + True + 1 + diff --git a/desmume/src/frontend/posix/gtk/main.cpp b/desmume/src/frontend/posix/gtk/main.cpp index 06f55c656..fe3b51105 100644 --- a/desmume/src/frontend/posix/gtk/main.cpp +++ b/desmume/src/frontend/posix/gtk/main.cpp @@ -1,17 +1,17 @@ /* Copyright (C) 2007 Pascal Giard (evilynux) Copyright (C) 2006-2024 DeSmuME team - + This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. - + This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with the this software. If not, see . */ @@ -56,8 +56,8 @@ #include "cheatsGTK.h" #include "frontend/modules/osd/agg/agg_osd.h" -#include "avout_x264.h" -#include "avout_flac.h" +#include "../shared/avout_x264.h" +#include "../shared/avout_flac.h" #include "commandline.h" @@ -72,17 +72,22 @@ #include "gdbstub.h" #endif -#define HAVE_OPENGL - -#ifdef HAVE_OPENGL - #include - #include "OGLRender_3_2.h" -#endif - -#if defined(HAVE_LIBOSMESA) - #include "osmesa_3Demu.h" -#else - #include "sdl_3Demu.h" +#if defined(ENABLE_OPENGL_STANDARD) || defined(ENABLE_OPENGL_ES) + #if defined(ENABLE_OPENGL_ES) + #include "OGLRender_ES3.h" + #else + #include "OGLRender_3_2.h" + #endif + + #if defined(ENABLE_GLX) + #include "../shared/glx_3Demu.h" + #elif defined(ENABLE_OSMESA) + #include "../shared/osmesa_3Demu.h" + #elif defined(ENABLE_EGL) + #include "../shared/egl_3Demu.h" + #else + #include "../shared/sdl_3Demu.h" + #endif #endif #include "config.h" @@ -344,11 +349,16 @@ NULL }; GPU3DInterface *core3DList[] = { - &gpu3DNull, - &gpu3DRasterize, -#ifdef HAVE_OPENGL - &gpu3Dgl, + &gpu3DNull, + &gpu3DRasterize, +#if defined(ENABLE_OPENGL_ES) + &gpu3Dgl_ES_3_0, +#elif defined(ENABLE_OPENGL_STANDARD) + &gpu3Dgl, + &gpu3DglOld, + &gpu3Dgl_3_2, #endif + NULL }; int multisampleSizes[] = {0, 2, 4, 8, 16, 32}; @@ -409,7 +419,7 @@ init_configured_features( class configured_features *config ) config->timeout = 0; /* use the default language */ - config->firmware_language = -1; + config->firmware_language = -1; /* If specified by --lang option the lang will change to choosed one */ config->firmware_language = config->language; @@ -423,7 +433,7 @@ fill_configured_features( class configured_features *config, { "3d-render", 0, 0, G_OPTION_ARG_INT, &config->engine_3d, "Select 3D rendering engine. Available engines:\n" "\t\t\t\t 0 = 3d disabled\n" "\t\t\t\t 1 = internal rasterizer (default)\n" -#ifdef HAVE_OPENGL +#if defined(ENABLE_OPENGL_STANDARD) || defined(ENABLE_OPENGL_ES) "\t\t\t\t 2 = opengl\n" #endif ,"ENGINE"}, @@ -467,12 +477,12 @@ fill_configured_features( class configured_features *config, // Check if the commandLine argument was actually passed if (config->engine_3d != -1) { if (config->engine_3d != 0 && config->engine_3d != 1 -#ifdef HAVE_OPENGL +#if defined(ENABLE_OPENGL_STANDARD) || defined(ENABLE_OPENGL_ES) && config->engine_3d != 2 #endif ) { g_printerr("Currently available ENGINES: 0, 1" -#ifdef HAVE_OPENGL +#if defined(ENABLE_OPENGL_STANDARD) || defined(ENABLE_OPENGL_ES) ", 2" #endif "\n"); @@ -1531,7 +1541,7 @@ static gboolean ExposeDrawingArea (GtkWidget *widget, GdkEventExpose *event, gpo if(nds_screen.orientation == ORIENT_HYBRID_EQUAL) draw_params.hybridBigScreenScale = (double)(dstH + draw_params.gap) / (double)(dstH / 2); } - + // Calculate scale to fit display area to window gfloat hratio = (gfloat)daW / (gfloat)draw_params.imgW; gfloat vratio = (gfloat)daH / (gfloat)draw_params.imgH; @@ -1821,7 +1831,7 @@ static gboolean Stylus_Release(GtkWidget *w, GdkEventButton *e, gpointer data) static void loadgame(int num){ if (desmume_running()) - { + { Pause(NULL, NULL, NULL); loadstate_slot(num); Launch(NULL, NULL, NULL); @@ -1833,7 +1843,7 @@ static void loadgame(int num){ static void savegame(int num){ if (desmume_running()) - { + { Pause(NULL, NULL, NULL); savestate_slot(num); Launch(NULL, NULL, NULL); @@ -2102,7 +2112,7 @@ static void Modify_JoyKey(GtkWidget* widget, gpointer data) gtk_widget_show_all(gtk_dialog_get_content_area(GTK_DIALOG(mkDialog))); g_signal_connect(G_OBJECT(mkDialog), "focus_in_event", G_CALLBACK(AcceptNewJoyKey), &ctx); - + switch(gtk_dialog_run(GTK_DIALOG(mkDialog))) { case GTK_RESPONSE_OK: Keypad_Temp[Key] = ctx.mk_key_chosen; @@ -2229,8 +2239,18 @@ static void GraphicsSettingsDialog(GSimpleAction *action, GVariant *parameter, g wHCInterpolate = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "hc_interpolate")); g_object_unref(builder); -#ifndef HAVE_OPENGL +#if defined(ENABLE_OPENGL_ES) + gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(coreCombo), 4); + gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(coreCombo), 3); + gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(coreCombo), 2); +#elif defined(ENABLE_OPENGL_STANDARD) + gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(coreCombo), 5); +#else + gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(coreCombo), 5); + gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(coreCombo), 4); + gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(coreCombo), 3); gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(coreCombo), 2); + gtk_grid_remove_row(wGrid, 5); gtk_grid_remove_row(wGrid, 4); #endif gtk_combo_box_set_active(coreCombo, cur3DCore); @@ -2247,7 +2267,7 @@ static void GraphicsSettingsDialog(GSimpleAction *action, GVariant *parameter, g // 3D Texture Smoothing gtk_toggle_button_set_active(wSmoothing, CommonSettings.GFX3D_Renderer_TextureSmoothing); -#ifdef HAVE_OPENGL +#if defined(ENABLE_OPENGL_STANDARD) || defined(ENABLE_OPENGL_ES) // OpenGL Multisample int currentMultisample = CommonSettings.GFX3D_Renderer_MultisampleSize; int currentActive = 0; @@ -2270,21 +2290,65 @@ static void GraphicsSettingsDialog(GSimpleAction *action, GVariant *parameter, g // Change only if needed if (sel3DCore != cur3DCore) { - if (sel3DCore == 2) + switch (sel3DCore) { -#if !defined(HAVE_OPENGL) - sel3DCore = RENDERID_SOFTRASTERIZER; -#elif defined(HAVE_LIBOSMESA) - if (!is_osmesa_initialized()) - { - init_osmesa_3Demu(); - } -#else - if (!is_sdl_initialized()) +#if defined(ENABLE_OPENGL_ES) && !defined(ENABLE_OSMESA) && !defined(ENABLE_GLX) + case 2: + #if defined(ENABLE_EGL) + oglrender_init = &egl_initOpenGL_ES_3_0; + #else + oglrender_init = &sdl_initOpenGL_ES_3_0; + #endif + break; +#elif defined(ENABLE_OPENGL_STANDARD) + case 2: + #if defined(ENABLE_GLX) + oglrender_init = &glx_initOpenGL_StandardAuto; + #elif defined(ENABLE_OSMESA) + oglrender_init = &osmesa_initOpenGL_StandardAuto; + #elif defined(ENABLE_EGL) + oglrender_init = &egl_initOpenGL_StandardAuto; + #else + oglrender_init = &sdl_initOpenGL_StandardAuto; + #endif + break; + + case 3: + #if defined(ENABLE_GLX) + oglrender_init = &glx_initOpenGL_LegacyAuto; + #elif defined(ENABLE_OSMESA) + oglrender_init = &osmesa_initOpenGL_LegacyAuto; + #elif defined(ENABLE_EGL) + oglrender_init = &egl_initOpenGL_LegacyAuto; + #else + oglrender_init = &sdl_initOpenGL_LegacyAuto; + #endif + break; + + case 4: + #if defined(ENABLE_GLX) + oglrender_init = &glx_initOpenGL_3_2_CoreProfile; + #elif defined(ENABLE_OSMESA) + oglrender_init = &osmesa_initOpenGL_3_2_CoreProfile; + #elif defined(ENABLE_EGL) + oglrender_init = &egl_initOpenGL_3_2_CoreProfile; + #else + oglrender_init = &sdl_initOpenGL_3_2_CoreProfile; + #endif + break; +#endif + default: { - init_sdl_3Demu(); + if (sel3DCore > 0) + { + sel3DCore = RENDERID_SOFTRASTERIZER; + } + else + { + sel3DCore = RENDERID_NULL; + } + break; } -#endif } if (GPU->Change3DRendererByID(sel3DCore)) @@ -2342,7 +2406,7 @@ static void GraphicsSettingsDialog(GSimpleAction *action, GVariant *parameter, g CommonSettings.GFX3D_Renderer_TextureSmoothing = config.textureSmoothing = gtk_toggle_button_get_active(wSmoothing); CommonSettings.GFX3D_Renderer_TextureScalingFactor = config.textureUpscale = scale; CommonSettings.GFX3D_HighResolutionInterpolateColor = config.highColorInterpolation = gtk_toggle_button_get_active(wHCInterpolate); -#ifdef HAVE_OPENGL +#if defined(ENABLE_OPENGL_STANDARD) || defined(ENABLE_OPENGL_ES) int selectedMultisample = gtk_combo_box_get_active(wMultisample); config.multisamplingSize = multisampleSizes[selectedMultisample]; config.multisampling = selectedMultisample != 0; @@ -2703,7 +2767,7 @@ class GtkDriver : public BaseDriver return avout_x264.isRecording() || avout_flac.isRecording(); } - virtual void AVI_SoundUpdate(void* soundData, int soundLen) { + virtual void AVI_SoundUpdate(void* soundData, int soundLen) { avout_flac.updateAudio(soundData, soundLen); } }; @@ -2774,7 +2838,7 @@ gboolean EmuLoop(gpointer data) #ifdef HAVE_LIBAGG Hud.fps3d = GPU->GetFPSRender3D(); - if(nds.idleFrameCounter==0 || oneSecond) + if (nds.idleFrameCounter==0 || oneSecond) { u32 loadAvgARM9; u32 loadAvgARM7; @@ -3266,7 +3330,7 @@ common_gtk_main(GApplication *app, gpointer user_data) slot2_device_type = NDS_SLOT2_NONE; break; } - + slot2_Init(); slot2_Change((NDS_SLOT2_TYPE)slot2_device_type); @@ -3304,7 +3368,7 @@ common_gtk_main(GApplication *app, gpointer user_data) arm9_gdb_stub = createStub_gdb( my_config->arm9_gdb_port, &NDS_ARM9, &arm9_direct_memory_iface); - + if ( arm9_gdb_stub == NULL) { g_printerr("Failed to create ARM9 gdbstub on port %d\n", my_config->arm9_gdb_port); @@ -3318,7 +3382,7 @@ common_gtk_main(GApplication *app, gpointer user_data) arm7_gdb_stub = createStub_gdb( my_config->arm7_gdb_port, &NDS_ARM7, &arm7_base_memory_iface); - + if ( arm7_gdb_stub == NULL) { g_printerr("Failed to create ARM7 gdbstub on port %d\n", my_config->arm7_gdb_port); @@ -3336,8 +3400,8 @@ common_gtk_main(GApplication *app, gpointer user_data) g_application_quit(app); dTools_running = (BOOL*)malloc(sizeof(BOOL) * dTools_list_size); - if (dTools_running != NULL) - memset(dTools_running, FALSE, sizeof(BOOL) * dTools_list_size); + if (dTools_running != NULL) + memset(dTools_running, FALSE, sizeof(BOOL) * dTools_list_size); keyfile = desmume_config_read_file(gtk_kb_cfg); @@ -3814,22 +3878,60 @@ common_gtk_main(GApplication *app, gpointer user_data) g_simple_action_set_state(G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "enablefpslimiter")), g_variant_new_boolean(FALSE)); } -#if defined(HAVE_OPENGL) && defined(OGLRENDER_3_2_H) +#if defined(ENABLE_OPENGL_STANDARD) || defined(ENABLE_OPENGL_ES) + #if defined(OGLRENDER_3_2_H) OGLLoadEntryPoints_3_2_Func = OGLLoadEntryPoints_3_2; OGLCreateRenderer_3_2_Func = OGLCreateRenderer_3_2; -#endif + #endif + #if defined(OGLRENDER_ES3_H) + OGLLoadEntryPoints_ES_3_0_Func = &OGLLoadEntryPoints_ES_3_0; + OGLCreateRenderer_ES_3_0_Func = &OGLCreateRenderer_ES_3_0; + #endif + + #if defined(ENABLE_GLX) + oglrender_init = &glx_initOpenGL_StandardAuto; + oglrender_deinit = &glx_deinitOpenGL; + oglrender_beginOpenGL = &glx_beginOpenGL; + oglrender_endOpenGL = &glx_endOpenGL; + oglrender_framebufferDidResizeCallback = &glx_framebufferDidResizeCallback; + #elif defined(ENABLE_OSMESA) + oglrender_init = &osmesa_initOpenGL_StandardAuto; + oglrender_deinit = &osmesa_deinitOpenGL; + oglrender_beginOpenGL = &osmesa_beginOpenGL; + oglrender_endOpenGL = &osmesa_endOpenGL; + oglrender_framebufferDidResizeCallback = &osmesa_framebufferDidResizeCallback; + #elif defined(ENABLE_EGL) + oglrender_init = &egl_initOpenGL_StandardAuto; + oglrender_deinit = &egl_deinitOpenGL; + oglrender_beginOpenGL = &egl_beginOpenGL; + oglrender_endOpenGL = &egl_endOpenGL; + oglrender_framebufferDidResizeCallback = &egl_framebufferDidResizeCallback; + #else + oglrender_init = &sdl_initOpenGL_StandardAuto; + oglrender_deinit = &sdl_deinitOpenGL; + oglrender_beginOpenGL = &sdl_beginOpenGL; + oglrender_endOpenGL = &sdl_endOpenGL; + oglrender_framebufferDidResizeCallback = &sdl_framebufferDidResizeCallback; + #endif +#endif // ENABLE_OPENGL_STANDARD || ENABLE_OPENGL_ES //Set the 3D emulation to use int core = my_config->engine_3d; // setup the gdk 3D emulation; // Check if commandLine argument was passed or not - if (core == -1) { + if (core == -1) + { // If it was not passed, then get the Renderer config from the file core = config.core3D; // Check if it is valid - if (!(core >= 0 && core <= 2)) { +#if defined(ENABLE_OPENGL_ES) + if (!(core >= 0 && core <= 2)) +#elif defined(ENABLE_OPENGL_STANDARD) + if (!(core >= 0 && core <= 4)) +#endif + { // If it is invalid, reset it to SoftRasterizer core = 1; } @@ -3837,21 +3939,65 @@ common_gtk_main(GApplication *app, gpointer user_data) my_config->engine_3d = core; } - if (core == 2) + switch (core) { -#if !defined(HAVE_OPENGL) - core = RENDERID_SOFTRASTERIZER; -#elif defined(HAVE_LIBOSMESA) - if (!is_osmesa_initialized()) - { - init_osmesa_3Demu(); - } -#else - if (!is_sdl_initialized()) +#if defined(ENABLE_OPENGL_ES) && !defined(ENABLE_OSMESA) && !defined(ENABLE_GLX) + case 2: + #if defined(ENABLE_EGL) + oglrender_init = &egl_initOpenGL_ES_3_0; + #else + oglrender_init = &sdl_initOpenGL_ES_3_0; + #endif + break; +#elif defined(ENABLE_OPENGL_STANDARD) + case 2: + #if defined(ENABLE_GLX) + oglrender_init = &glx_initOpenGL_StandardAuto; + #elif defined(ENABLE_OSMESA) + oglrender_init = &osmesa_initOpenGL_StandardAuto; + #elif defined(ENABLE_EGL) + oglrender_init = &egl_initOpenGL_StandardAuto; + #else + oglrender_init = &sdl_initOpenGL_StandardAuto; + #endif + break; + + case 3: + #if defined(ENABLE_GLX) + oglrender_init = &glx_initOpenGL_LegacyAuto; + #elif defined(ENABLE_OSMESA) + oglrender_init = &osmesa_initOpenGL_LegacyAuto; + #elif defined(ENABLE_EGL) + oglrender_init = &egl_initOpenGL_LegacyAuto; + #else + oglrender_init = &sdl_initOpenGL_LegacyAuto; + #endif + break; + + case 4: + #if defined(ENABLE_GLX) + oglrender_init = &glx_initOpenGL_3_2_CoreProfile; + #elif defined(ENABLE_OSMESA) + oglrender_init = &osmesa_initOpenGL_3_2_CoreProfile; + #elif defined(ENABLE_EGL) + oglrender_init = &egl_initOpenGL_3_2_CoreProfile; + #else + oglrender_init = &sdl_initOpenGL_3_2_CoreProfile; + #endif + break; +#endif + default: { - init_sdl_3Demu(); + if (core > 0) + { + core = RENDERID_SOFTRASTERIZER; + } + else + { + core = RENDERID_NULL; + } + break; } -#endif } if (!GPU->Change3DRendererByID(core)) { @@ -3873,7 +4019,7 @@ common_gtk_main(GApplication *app, gpointer user_data) backup_setManualBackupType(my_config->savetype); - // Command line arg + // Command line arg if( my_config->nds_file != "") { if(Open( my_config->nds_file.c_str()) >= 0) { my_config->process_movieCommands(); @@ -3923,11 +4069,17 @@ static void Teardown() { desmume_free(); -#if defined(HAVE_LIBOSMESA) - deinit_osmesa_3Demu(); -#else - deinit_sdl_3Demu(); -#endif +#if defined(ENABLE_OPENGL_STANDARD) || defined(ENABLE_OPENGL_ES) + #if defined(ENABLE_GLX) + glx_deinitOpenGL(); + #elif defined(ENABLE_OSMESA) + osmesa_deinitOpenGL(); + #elif defined(ENABLE_EGL) + egl_deinitOpenGL(); + #else + sdl_deinitOpenGL(); + #endif +#endif // ENABLE_OPENGL_STANDARD || ENABLE_OPENGL_ES /* Unload joystick */ uninit_joy(); diff --git a/desmume/src/frontend/posix/gtk/meson.build b/desmume/src/frontend/posix/gtk/meson.build index 99d6fd1dc..2bdc70356 100644 --- a/desmume/src/frontend/posix/gtk/meson.build +++ b/desmume/src/frontend/posix/gtk/meson.build @@ -10,22 +10,44 @@ gresource = gnome.compile_resources( ) desmume_src = [ - 'avout_pipe_base.cpp', - 'avout_x264.cpp', - 'avout_flac.cpp', + '../shared/avout_flac.cpp', + '../shared/avout_pipe_base.cpp', + '../shared/avout_x264.cpp', + '../shared/ctrlssdl.cpp', + '../shared/sndsdl.cpp', 'config.cpp', 'desmume.cpp', 'dToolsList.cpp', 'tools/ioregsView.cpp', - '../shared/sndsdl.cpp', - '../shared/ctrlssdl.cpp', - 'osmesa_3Demu.cpp', - 'sdl_3Demu.cpp', 'cheatsGTK.cpp', 'main.cpp', gresource, ] +if get_option('glx') and dep_glx.found() + add_global_arguments('-DENABLE_GLX', language: ['c', 'cpp']) + dependencies += dep_glx + desmume_src += [ + '../shared/glx_3Demu.cpp', + ] +elif get_option('osmesa') and dep_osmesa.found() + add_global_arguments('-DENABLE_OSMESA', language: ['c', 'cpp']) + dependencies += dep_osmesa + desmume_src += [ + '../shared/osmesa_3Demu.cpp', + ] +elif get_option('egl') and dep_egl.found() + add_global_arguments('-DENABLE_EGL', language: ['c', 'cpp']) + dependencies += dep_egl + desmume_src += [ + '../shared/egl_3Demu.cpp', + ] +else + desmume_src += [ + '../shared/sdl_3Demu.cpp', + ] +endif + # TODO: why do we have to redeclare it here with one more fs level? includes = include_directories( '../../../../src', diff --git a/desmume/src/frontend/posix/gtk/osmesa_3Demu.cpp b/desmume/src/frontend/posix/gtk/osmesa_3Demu.cpp deleted file mode 100644 index 78bf89a2e..000000000 --- a/desmume/src/frontend/posix/gtk/osmesa_3Demu.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - Copyright (C) 2009 Guillaume Duhamel - Copyright (C) 2009-2024 DeSmuME team - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the this software. If not, see . - */ - -#ifdef HAVE_LIBOSMESA - -#include -#include -#include "../OGLRender_3_2.h" - -#include "osmesa_3Demu.h" - -static void *buffer = NULL; -static OSMesaContext ctx = NULL; - -static bool osmesa_beginOpenGL(void) { return 1; } -static void osmesa_endOpenGL(void) { } -static bool osmesa_init(void) { return is_osmesa_initialized(); } - -void deinit_osmesa_3Demu (void) -{ - free(buffer); - buffer = NULL; - - OSMesaDestroyContext(ctx); - ctx = NULL; -} - -bool init_osmesa_3Demu(void) -{ -#if (((OSMESA_MAJOR_VERSION * 100) + OSMESA_MINOR_VERSION) >= 1102) && defined(OSMESA_CONTEXT_MAJOR_VERSION) - static const int attributes_3_2_core_profile[] = { - OSMESA_FORMAT, OSMESA_RGBA, - OSMESA_DEPTH_BITS, 24, - OSMESA_STENCIL_BITS, 8, - OSMESA_ACCUM_BITS, 0, - OSMESA_PROFILE, OSMESA_CORE_PROFILE, - OSMESA_CONTEXT_MAJOR_VERSION, 3, - OSMESA_CONTEXT_MINOR_VERSION, 2, - 0 }; - - ctx = OSMesaCreateContextAttribs(attributes_3_2_core_profile, NULL); - if (ctx == NULL) - { - printf("OSMesa: Could not create a 3.2 Core Profile context. Will attempt to create a 2.1 compatibility context...\n"); - - static const int attributes_2_1[] = { - OSMESA_FORMAT, OSMESA_RGBA, - OSMESA_DEPTH_BITS, 24, - OSMESA_STENCIL_BITS, 8, - OSMESA_ACCUM_BITS, 0, - OSMESA_PROFILE, OSMESA_COMPAT_PROFILE, - OSMESA_CONTEXT_MAJOR_VERSION, 2, - OSMESA_CONTEXT_MINOR_VERSION, 1, - 0 }; - - ctx = OSMesaCreateContextAttribs(attributes_2_1, NULL); - } -#endif - - if (ctx == NULL) - { - ctx = OSMesaCreateContextExt(OSMESA_RGBA, 24, 8, 0, NULL); - if (ctx == NULL) - { - printf("OSMesa: OSMesaCreateContextExt() failed!\n"); - return false; - } - } - - buffer = malloc(GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * sizeof(uint32_t)); - if (!buffer) - { - printf("OSMesa: Could not allocate enough memory for the context!\n"); - return false; - } - - if (!OSMesaMakeCurrent(ctx, buffer, GL_UNSIGNED_BYTE, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT)) - { - printf("OSMesa: OSMesaMakeCurrent() failed!\n"); - free(buffer); - return false; - } - - oglrender_init = osmesa_init; - oglrender_beginOpenGL = osmesa_beginOpenGL; - oglrender_endOpenGL = osmesa_endOpenGL; - - return true; -} - -bool is_osmesa_initialized(void) -{ - return (ctx != NULL); -} - -#endif diff --git a/desmume/src/frontend/posix/gtk/osmesa_3Demu.h b/desmume/src/frontend/posix/gtk/osmesa_3Demu.h deleted file mode 100644 index af6a9f4db..000000000 --- a/desmume/src/frontend/posix/gtk/osmesa_3Demu.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - Copyright (C) 2009 Guillaume Duhamel - Copyright (C) 2009-2017 DeSmuME team - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the this software. If not, see . - */ - -#ifndef OSMESA_3DEMU_H -#define OSMESA_3DEMU_H - -bool init_osmesa_3Demu(void); -void deinit_osmesa_3Demu(void); -bool is_osmesa_initialized(void); - -#endif // OSMESA_3DEMU_H - diff --git a/desmume/src/frontend/posix/gtk/sdl_3Demu.cpp b/desmume/src/frontend/posix/gtk/sdl_3Demu.cpp deleted file mode 100644 index 39c5d0d57..000000000 --- a/desmume/src/frontend/posix/gtk/sdl_3Demu.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright (C) 2020 Emmanuel Gil Peyrot - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the this software. If not, see . - */ - -#include -#include -#include "../OGLRender.h" - -#include "sdl_3Demu.h" - -static bool sdl_beginOpenGL(void) { return 1; } -static void sdl_endOpenGL(void) { } -static bool sdl_init(void) { return is_sdl_initialized(); } - -static SDL_Window *win = NULL; -static SDL_GLContext ctx = NULL; - -extern int real_framebuffer_width; -extern int real_framebuffer_height; - -bool deinit_sdl_3Demu(void) -{ - bool ret = false; - - if (ctx) { - SDL_GL_DeleteContext(ctx); - ctx = NULL; - ret = true; - } - - if (win) { - SDL_DestroyWindow(win); - win = NULL; - ret = true; - } - - return ret; -} - -bool init_sdl_3Demu(void) -{ - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); - SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); - - win = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, real_framebuffer_width, - real_framebuffer_height, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN); - if (!win) { - fprintf(stderr, "SDL: Failed to create a window: %s\n", SDL_GetError()); - return false; - } - - ctx = SDL_GL_CreateContext(win); - if (!ctx) { - fprintf(stderr, "SDL: Failed to create an OpenGL context: %s\n", SDL_GetError()); - return false; - } - - printf("OGL/SDL Renderer has finished the initialization.\n"); - - oglrender_init = sdl_init; - oglrender_beginOpenGL = sdl_beginOpenGL; - oglrender_endOpenGL = sdl_endOpenGL; - - return true; -} - -bool is_sdl_initialized(void) -{ - return (ctx != NULL); -} diff --git a/desmume/src/frontend/posix/gtk/sdl_3Demu.h b/desmume/src/frontend/posix/gtk/sdl_3Demu.h deleted file mode 100644 index 2088263da..000000000 --- a/desmume/src/frontend/posix/gtk/sdl_3Demu.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - Copyright (C) 2020 Emmanuel Gil Peyrot - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the this software. If not, see . - */ - -#ifndef SDL_3DEMU_H -#define SDL_3DEMU_H - -bool init_sdl_3Demu(void); -bool deinit_sdl_3Demu(void); -bool is_sdl_initialized(void); - -#endif // SDL_3DEMU_H - diff --git a/desmume/src/frontend/posix/gtk2/Makefile.am b/desmume/src/frontend/posix/gtk2/Makefile.am index 9ba2a51b4..1f155dc45 100644 --- a/desmume/src/frontend/posix/gtk2/Makefile.am +++ b/desmume/src/frontend/posix/gtk2/Makefile.am @@ -9,26 +9,47 @@ pixmapdir = $(datadir)/pixmaps pixmap_DATA = DeSmuME.xpm EXTRA_DIST = DeSmuME.xpm desmume.desktop bin_PROGRAMS = desmume + desmume_SOURCES = \ - avout.h \ - avout_pipe_base.cpp avout_pipe_base.h \ - avout_x264.cpp avout_x264.h \ - avout_flac.cpp avout_flac.h \ + ../shared/avout.h \ + ../shared/avout_flac.h ../shared/avout_flac.cpp \ + ../shared/avout_pipe_base.h ../shared/avout_pipe_base.cpp \ + ../shared/avout_x264.h ../shared/avout_x264.cpp \ + ../shared/ctrlssdl.h ../shared/ctrlssdl.cpp \ + ../shared/sndsdl.cpp \ config.cpp config.h config_opts.h \ desmume.h desmume.cpp \ dTool.h dToolsList.cpp \ tools/ioregsView.cpp tools/ioregsView.h \ - ../shared/sndsdl.cpp \ - ../shared/ctrlssdl.h ../shared/ctrlssdl.cpp \ - osmesa_3Demu.cpp osmesa_3Demu.h \ - sdl_3Demu.cpp sdl_3Demu.h \ cheatsGTK.h cheatsGTK.cpp \ main.cpp main.h + desmume_LDADD = ../libdesmume.a \ $(X_LIBS) -lX11 $(SDL_LIBS) $(GTK_LIBS) $(GTHREAD_LIBS) $(ALSA_LIBS) $(LIBAGG_LIBS) $(LIBSOUNDTOUCH_LIBS) -if HAVE_LIBOSMESA + +if ENABLE_OPENGL_ES +desmume_LDADD += $(OPENGLES_LIBS) +else +if ENABLE_OPENGL_STANDARD +desmume_LDADD += $(OPENGL_LIBS) +endif +endif + +if ENABLE_GLX +desmume_LDADD += $(GLX_LIBS) +desmume_SOURCES += ../shared/glx_3Demu.h ../shared/glx_3Demu.cpp +else +if ENABLE_OSMESA desmume_LDADD += $(OSMESA_LIBS) +desmume_SOURCES += ../shared/osmesa_3Demu.h ../shared/osmesa_3Demu.cpp else +if ENABLE_EGL +desmume_LDADD += $(EGL_LIBS) +desmume_SOURCES += ../shared/egl_3Demu.h ../shared/egl_3Demu.cpp +else +desmume_SOURCES += ../shared/sdl_3Demu.h ../shared/sdl_3Demu.cpp +endif +endif endif UPDATE_DESKTOP = \ @@ -43,4 +64,4 @@ install-data-hook: $(UPDATE_DESKTOP) uninstall-hook: - $(UPDATE_DESKTOP) + $(UPDATE_DESKTOP) diff --git a/desmume/src/frontend/posix/gtk2/avout_flac.cpp b/desmume/src/frontend/posix/gtk2/avout_flac.cpp deleted file mode 100644 index a45e77bc0..000000000 --- a/desmume/src/frontend/posix/gtk2/avout_flac.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copyright (C) 2014 DeSmuME team - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the this software. If not, see . -*/ - -#include -#include - -#include "avout_flac.h" -#include "SPU.h" - -// Helper macros to convert numerics to strings -#if defined(_MSC_VER) - //re: http://72.14.203.104/search?q=cache:HG-okth5NGkJ:mail.python.org/pipermail/python-checkins/2002-November/030704.html+_msc_ver+compiler+version+string&hl=en&gl=us&ct=clnk&cd=5 - #define _Py_STRINGIZE(X) _Py_STRINGIZE1((X)) - #define _Py_STRINGIZE1(X) _Py_STRINGIZE2 ## X - #define _Py_STRINGIZE2(X) #X - - #define TOSTRING(X) _Py_STRINGIZE(X) // Alias _Py_STRINGIZE so that we have a common macro name -#else - #define STRINGIFY(x) #x - #define TOSTRING(x) STRINGIFY(x) -#endif - -AVOutFlac::AVOutFlac() { - const char* const args[] = { - "flac", - "-f", - "-o", this->filename, - "--endian=little", - "--channels=2", - "--bps=16", - "--sample-rate=" TOSTRING(DESMUME_SAMPLE_RATE), - "--sign=signed", - "--force-raw-format", - "-", - NULL - }; - memcpy(this->args, args, sizeof(args)); -} - -const char* const* AVOutFlac::getArgv(const char* fname) { - if (strlen(fname) >= sizeof(this->filename)) { - return NULL; - } - strncpy(this->filename, fname, sizeof(this->filename)); - return this->args; -} - diff --git a/desmume/src/frontend/posix/gtk2/avout_flac.h b/desmume/src/frontend/posix/gtk2/avout_flac.h deleted file mode 100644 index 818d81665..000000000 --- a/desmume/src/frontend/posix/gtk2/avout_flac.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - Copyright (C) 2014 DeSmuME team - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the this software. If not, see . -*/ - -#ifndef _AVOUT_FLAC_H_ -#define _AVOUT_FLAC_H_ - -#include "avout_pipe_base.h" - -class AVOutFlac : public AVOutPipeBase { -public: - AVOutFlac(); -protected: - Type type() { return TYPE_AUDIO; } - const char* const* getArgv(const char* fname); -private: - char filename[1024]; - const char* args[12]; -}; - -#endif diff --git a/desmume/src/frontend/posix/gtk2/avout_pipe_base.cpp b/desmume/src/frontend/posix/gtk2/avout_pipe_base.cpp deleted file mode 100644 index fa4f5d431..000000000 --- a/desmume/src/frontend/posix/gtk2/avout_pipe_base.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - Copyright (C) 2014 DeSmuME team - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the this software. If not, see . -*/ - -#include -#include - -#include "types.h" -#include "SPU.h" - -#include "avout_pipe_base.h" - -static inline int writeAll(int fd, const void* buf, size_t count) { - ssize_t written = 0, writtenTotal = 0; - do { - written = write(fd, ((u8*)buf) + writtenTotal, count - writtenTotal); - } while (written >= 0 && (writtenTotal += written) < count); - return written; -} - -bool AVOutPipeBase::begin(const char* fname) { - if (this->recording) { - return false; - } - const char* const* args = this->getArgv(fname); - if (args == NULL) { - return false; - } - int pipefd[2]; - if (pipe(pipefd) < 0) { - fprintf(stderr, "Fail to open pipe\n"); - return false; - } - pid_t pid = fork(); - if (pid == 0) { - close(pipefd[1]); - dup2(pipefd[0], STDIN_FILENO); - execvp(args[0], (char* const*)args); - fprintf(stderr, "Fail to start %s: %d %s\n", args[0], errno, strerror(errno)); - _exit(1); - } - close(pipefd[0]); - this->pipe_fd = pipefd[1]; - this->recording = true; - return true; -} - -void AVOutPipeBase::end() { - if (this->recording) { - close(this->pipe_fd); - this->recording = false; - } -} - -bool AVOutPipeBase::isRecording() { - return this->recording; -} - -void AVOutPipeBase::updateAudio(void* soundData, int soundLen) { - if(!this->recording || this->type() != TYPE_AUDIO) { - return; - } - if (writeAll(this->pipe_fd, soundData, soundLen * 2 * 2) == -1) { - fprintf(stderr, "Error on writing audio: %d %s\n", errno, strerror(errno)); - this->end(); - } -} - -void AVOutPipeBase::updateVideo(const u16* buffer) { - if(!this->recording || this->type() != TYPE_VIDEO) { - return; - } - u8 rgb[256 * 384 * 3]; - u8* cur = rgb; - for (int i = 0; i < 256 * 384; i++) { - u16 gpu_pixel = buffer[i]; - *cur = ((gpu_pixel >> 0) & 0x1f) << 3; - cur++; - *cur = ((gpu_pixel >> 5) & 0x1f) << 3; - cur++; - *cur = ((gpu_pixel >> 10) & 0x1f) << 3; - cur++; - } - if (write(this->pipe_fd, rgb, 256 * 384 * 3) == -1) { - fprintf(stderr, "Error on writing video: %d %s\n", errno, strerror(errno)); - this->end(); - } -} - diff --git a/desmume/src/frontend/posix/gtk2/avout_pipe_base.h b/desmume/src/frontend/posix/gtk2/avout_pipe_base.h deleted file mode 100644 index 3f1c0edd8..000000000 --- a/desmume/src/frontend/posix/gtk2/avout_pipe_base.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - Copyright (C) 2014 DeSmuME team - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the this software. If not, see . -*/ - -#ifndef _AVOUT_PIPE_BASE_H_ -#define _AVOUT_PIPE_BASE_H_ - -#include "avout.h" - -class AVOutPipeBase : public AVOut { -public: - bool begin(const char* fname); - void end(); - bool isRecording(); - void updateAudio(void* soundData, int soundLen); - void updateVideo(const u16* buffer); -protected: - enum Type { TYPE_AUDIO, TYPE_VIDEO }; - virtual Type type() = 0; - virtual const char* const* getArgv(const char* fname) = 0; -private: - bool recording; - int pipe_fd; -}; - -#endif diff --git a/desmume/src/frontend/posix/gtk2/avout_x264.cpp b/desmume/src/frontend/posix/gtk2/avout_x264.cpp deleted file mode 100644 index 1996c0f8a..000000000 --- a/desmume/src/frontend/posix/gtk2/avout_x264.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - Copyright (C) 2014 DeSmuME team - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the this software. If not, see . -*/ - -#include -#include - -#include "avout_x264.h" - -AVOutX264::AVOutX264() { - const char* const args[] = { - "x264", - "--qp", "0", - "--demuxer", "raw", - "--input-csp", "rgb", - "--input-depth", "8", - "--input-res", "256x384", - "--fps", "60", - "--output-csp", "i444", - "-o", this->filename, - "-", - NULL - }; - memcpy(this->args, args, sizeof(args)); -} - -const char* const* AVOutX264::getArgv(const char* fname) { - if (strlen(fname) >= sizeof(this->filename)) { - return NULL; - } - strncpy(this->filename, fname, sizeof(this->filename)); - return this->args; -} - diff --git a/desmume/src/frontend/posix/gtk2/main.cpp b/desmume/src/frontend/posix/gtk2/main.cpp index cee54cd60..a5450b719 100644 --- a/desmume/src/frontend/posix/gtk2/main.cpp +++ b/desmume/src/frontend/posix/gtk2/main.cpp @@ -1,17 +1,17 @@ /* Copyright (C) 2007 Pascal Giard (evilynux) Copyright (C) 2006-2024 DeSmuME team - + This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. - + This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with the this software. If not, see . */ @@ -52,8 +52,8 @@ #include "cheatsGTK.h" #include "frontend/modules/osd/agg/agg_osd.h" -#include "avout_x264.h" -#include "avout_flac.h" +#include "../shared/avout_x264.h" +#include "../shared/avout_flac.h" #include "commandline.h" @@ -68,17 +68,22 @@ #include "gdbstub.h" #endif -#define HAVE_OPENGL - -#ifdef HAVE_OPENGL - #include - #include "OGLRender_3_2.h" -#endif - -#if defined(HAVE_LIBOSMESA) - #include "osmesa_3Demu.h" -#else - #include "sdl_3Demu.h" +#if defined(ENABLE_OPENGL_STANDARD) || defined(ENABLE_OPENGL_ES) + #if defined(ENABLE_OPENGL_ES) + #include "OGLRender_ES3.h" + #else + #include "OGLRender_3_2.h" + #endif + + #if defined(ENABLE_GLX) + #include "../shared/glx_3Demu.h" + #elif defined(ENABLE_OSMESA) + #include "../shared/osmesa_3Demu.h" + #elif defined(ENABLE_EGL) + #include "../shared/egl_3Demu.h" + #else + #include "../shared/sdl_3Demu.h" + #endif #endif #include "config.h" @@ -396,7 +401,7 @@ static const char *ui_description = " " " " ""; - + static const GtkActionEntry action_entries[] = { { "FileMenu", NULL, "_File" }, { "open", "gtk-open", "_Open", "o", NULL, OpenNdsDialog }, @@ -632,11 +637,16 @@ NULL }; GPU3DInterface *core3DList[] = { - &gpu3DNull, - &gpu3DRasterize, -#ifdef HAVE_OPENGL - &gpu3Dgl, + &gpu3DNull, + &gpu3DRasterize, +#if defined(ENABLE_OPENGL_ES) + &gpu3Dgl_ES_3_0, +#elif defined(ENABLE_OPENGL_STANDARD) + &gpu3Dgl, + &gpu3DglOld, + &gpu3Dgl_3_2, #endif + NULL }; int multisampleSizes[] = {0, 2, 4, 8, 16, 32}; @@ -698,7 +708,7 @@ init_configured_features( class configured_features *config ) config->timeout = 0; /* use the default language */ - config->firmware_language = -1; + config->firmware_language = -1; /* If specified by --lang option the lang will change to choosed one */ config->firmware_language = config->language; @@ -712,7 +722,7 @@ fill_configured_features( class configured_features *config, { "3d-render", 0, 0, G_OPTION_ARG_INT, &config->engine_3d, "Select 3D rendering engine. Available engines:\n" "\t\t\t\t 0 = 3d disabled\n" "\t\t\t\t 1 = internal rasterizer (default)\n" -#ifdef HAVE_OPENGL +#if defined(ENABLE_OPENGL_STANDARD) || defined(ENABLE_OPENGL_ES) "\t\t\t\t 2 = opengl\n" #endif ,"ENGINE"}, @@ -756,12 +766,12 @@ fill_configured_features( class configured_features *config, // Check if the commandLine argument was actually passed if (config->engine_3d != -1) { if (config->engine_3d != 0 && config->engine_3d != 1 -#ifdef HAVE_OPENGL +#if defined(ENABLE_OPENGL_STANDARD) || defined(ENABLE_OPENGL_ES) && config->engine_3d != 2 #endif ) { g_printerr("Currently available ENGINES: 0, 1" -#ifdef HAVE_OPENGL +#if defined(ENABLE_OPENGL_STANDARD) || defined(ENABLE_OPENGL_ES) ", 2" #endif "\n"); @@ -1954,7 +1964,7 @@ static gboolean Stylus_Release(GtkWidget *w, GdkEventButton *e, gpointer data) static void loadgame(int num){ if (desmume_running()) - { + { Pause(); loadstate_slot(num); Launch(); @@ -1966,7 +1976,7 @@ static void loadgame(int num){ static void savegame(int num){ if (desmume_running()) - { + { Pause(); savestate_slot(num); Launch(); @@ -2247,7 +2257,7 @@ static void Modify_JoyKey(GtkWidget* widget, gpointer data) gtk_widget_show_all(gtk_dialog_get_content_area(GTK_DIALOG(mkDialog))); g_signal_connect(G_OBJECT(mkDialog), "focus_in_event", G_CALLBACK(AcceptNewJoyKey), &ctx); - + switch(gtk_dialog_run(GTK_DIALOG(mkDialog))) { case GTK_RESPONSE_OK: Keypad_Temp[Key] = ctx.mk_key_chosen; @@ -2403,8 +2413,12 @@ static void GraphicsSettingsDialog() { coreCombo = gtk_combo_box_text_new(); gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(coreCombo), 0, "Null"); gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(coreCombo), 1, "SoftRasterizer"); -#ifdef HAVE_OPENGL - gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(coreCombo), 2, "OpenGL"); +#if defined(ENABLE_OPENGL_ES) + gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(coreCombo), 2, "OpenGL ES 3.0"); +#elif defined(ENABLE_OPENGL_STANDARD) + gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(coreCombo), 2, "OpenGL (Auto)"); + gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(coreCombo), 3, "OpenGL (Legacy)"); + gtk_combo_box_text_insert_text(GTK_COMBO_BOX_TEXT(coreCombo), 4, "OpenGL 3.2"); #endif gtk_combo_box_set_active(GTK_COMBO_BOX(coreCombo), cur3DCore); gtk_table_attach(GTK_TABLE(wTable), coreCombo, 1, 2, 0, 1, @@ -2447,7 +2461,7 @@ static void GraphicsSettingsDialog() { static_cast(GTK_EXPAND | GTK_FILL), 0, 0); -#ifdef HAVE_OPENGL +#if defined(ENABLE_OPENGL_STANDARD) || defined(ENABLE_OPENGL_ES) // OpenGL Multisample gsKey = gtk_label_new("Multisample Antialiasing (OpenGL):"); gtk_misc_set_alignment(GTK_MISC(gsKey), 0.0, 0.5); @@ -2492,21 +2506,65 @@ static void GraphicsSettingsDialog() { // Change only if needed if (sel3DCore != cur3DCore) { - if (sel3DCore == 2) + switch (sel3DCore) { -#if !defined(HAVE_OPENGL) - sel3DCore = RENDERID_SOFTRASTERIZER; -#elif defined(HAVE_LIBOSMESA) - if (!is_osmesa_initialized()) - { - init_osmesa_3Demu(); - } -#else - if (!is_sdl_initialized()) +#if defined(ENABLE_OPENGL_ES) && !defined(ENABLE_OSMESA) && !defined(ENABLE_GLX) + case 2: + #if defined(ENABLE_EGL) + oglrender_init = &egl_initOpenGL_ES_3_0; + #else + oglrender_init = &sdl_initOpenGL_ES_3_0; + #endif + break; +#elif defined(ENABLE_OPENGL_STANDARD) + case 2: + #if defined(ENABLE_GLX) + oglrender_init = &glx_initOpenGL_StandardAuto; + #elif defined(ENABLE_OSMESA) + oglrender_init = &osmesa_initOpenGL_StandardAuto; + #elif defined(ENABLE_EGL) + oglrender_init = &egl_initOpenGL_StandardAuto; + #else + oglrender_init = &sdl_initOpenGL_StandardAuto; + #endif + break; + + case 3: + #if defined(ENABLE_GLX) + oglrender_init = &glx_initOpenGL_LegacyAuto; + #elif defined(ENABLE_OSMESA) + oglrender_init = &osmesa_initOpenGL_LegacyAuto; + #elif defined(ENABLE_EGL) + oglrender_init = &egl_initOpenGL_LegacyAuto; + #else + oglrender_init = &sdl_initOpenGL_LegacyAuto; + #endif + break; + + case 4: + #if defined(ENABLE_GLX) + oglrender_init = &glx_initOpenGL_3_2_CoreProfile; + #elif defined(ENABLE_OSMESA) + oglrender_init = &osmesa_initOpenGL_3_2_CoreProfile; + #elif defined(ENABLE_EGL) + oglrender_init = &egl_initOpenGL_3_2_CoreProfile; + #else + oglrender_init = &sdl_initOpenGL_3_2_CoreProfile; + #endif + break; +#endif + default: { - init_sdl_3Demu(); + if (sel3DCore > 0) + { + sel3DCore = RENDERID_SOFTRASTERIZER; + } + else + { + sel3DCore = RENDERID_NULL; + } + break; } -#endif } if (GPU->Change3DRendererByID(sel3DCore)) @@ -2537,7 +2595,7 @@ static void GraphicsSettingsDialog() { CommonSettings.GFX3D_Renderer_TextureSmoothing = config.textureSmoothing = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wSmoothing)); CommonSettings.GFX3D_Renderer_TextureScalingFactor = config.textureUpscale = scale; CommonSettings.GFX3D_HighResolutionInterpolateColor = config.highColorInterpolation = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wHCInterpolate)); -#ifdef HAVE_OPENGL +#if defined(ENABLE_OPENGL_STANDARD) || defined(ENABLE_OPENGL_ES) int selectedMultisample = gtk_combo_box_get_active(GTK_COMBO_BOX(wMultisample)); config.multisamplingSize = multisampleSizes[selectedMultisample]; config.multisampling = selectedMultisample != 0; @@ -2812,7 +2870,7 @@ class GtkDriver : public BaseDriver return avout_x264.isRecording() || avout_flac.isRecording(); } - virtual void AVI_SoundUpdate(void* soundData, int soundLen) { + virtual void AVI_SoundUpdate(void* soundData, int soundLen) { avout_flac.updateAudio(soundData, soundLen); } }; @@ -2876,7 +2934,7 @@ gboolean EmuLoop(gpointer data) #ifdef HAVE_LIBAGG Hud.fps3d = GPU->GetFPSRender3D(); - if(nds.idleFrameCounter==0 || oneSecond) + if (nds.idleFrameCounter==0 || oneSecond) { u32 loadAvgARM9; u32 loadAvgARM7; @@ -3310,7 +3368,7 @@ common_gtk_main( class configured_features *my_config) slot2_device_type = NDS_SLOT2_NONE; break; } - + slot2_Init(); slot2_Change((NDS_SLOT2_TYPE)slot2_device_type); @@ -3338,15 +3396,15 @@ common_gtk_main( class configured_features *my_config) */ #ifdef GDB_STUB gdbstub_mutex_init(); - + gdbstub_handle_t arm9_gdb_stub = NULL; gdbstub_handle_t arm7_gdb_stub = NULL; - + if ( my_config->arm9_gdb_port > 0) { arm9_gdb_stub = createStub_gdb( my_config->arm9_gdb_port, &NDS_ARM9, &arm9_direct_memory_iface); - + if ( arm9_gdb_stub == NULL) { g_printerr("Failed to create ARM9 gdbstub on port %d\n", my_config->arm9_gdb_port); @@ -3360,7 +3418,7 @@ common_gtk_main( class configured_features *my_config) arm7_gdb_stub = createStub_gdb( my_config->arm7_gdb_port, &NDS_ARM7, &arm7_base_memory_iface); - + if ( arm7_gdb_stub == NULL) { g_printerr("Failed to create ARM7 gdbstub on port %d\n", my_config->arm7_gdb_port); @@ -3376,8 +3434,8 @@ common_gtk_main( class configured_features *my_config) if(!init_joy()) return 1; dTools_running = (BOOL*)malloc(sizeof(BOOL) * dTools_list_size); - if (dTools_running != NULL) - memset(dTools_running, FALSE, sizeof(BOOL) * dTools_list_size); + if (dTools_running != NULL) + memset(dTools_running, FALSE, sizeof(BOOL) * dTools_list_size); keyfile = desmume_config_read_file(gtk_kb_cfg); @@ -3421,21 +3479,21 @@ common_gtk_main( class configured_features *my_config) #endif desmume_gtk_menu_file_saveload_slot(action_group); desmume_gtk_menu_tools(action_group); - gtk_action_group_add_radio_actions(action_group, savet_entries, G_N_ELEMENTS(savet_entries), + gtk_action_group_add_radio_actions(action_group, savet_entries, G_N_ELEMENTS(savet_entries), my_config->savetype, G_CALLBACK(changesavetype), NULL); if (config.view_cairoFilter < CAIRO_FILTER_FAST || config.view_cairoFilter > CAIRO_FILTER_BILINEAR) { config.view_cairoFilter = CAIRO_FILTER_NEAREST; } Interpolation = (cairo_filter_t)config.view_cairoFilter.get(); - gtk_action_group_add_radio_actions(action_group, interpolation_entries, G_N_ELEMENTS(interpolation_entries), + gtk_action_group_add_radio_actions(action_group, interpolation_entries, G_N_ELEMENTS(interpolation_entries), Interpolation, G_CALLBACK(Modify_Interpolation), NULL); if (config.view_filter < VideoFilterTypeID_None || config.view_filter >= VideoFilterTypeIDCount) { config.view_filter = VideoFilterTypeID_None; } video->ChangeFilterByID((VideoFilterTypeID)config.view_filter.get()); - gtk_action_group_add_radio_actions(action_group, pri_interpolation_entries, G_N_ELEMENTS(pri_interpolation_entries), + gtk_action_group_add_radio_actions(action_group, pri_interpolation_entries, G_N_ELEMENTS(pri_interpolation_entries), config.view_filter, G_CALLBACK(Modify_PriInterpolation), NULL); switch (config.audio_sync) { @@ -3462,7 +3520,7 @@ common_gtk_main( class configured_features *my_config) gtk_action_group_add_radio_actions(action_group, spuinterpolation_entries, G_N_ELEMENTS(spuinterpolation_entries), CommonSettings.spuInterpolationMode, G_CALLBACK(Modify_SPUInterpolation), NULL); - gtk_action_group_add_radio_actions(action_group, frameskip_entries, G_N_ELEMENTS(frameskip_entries), + gtk_action_group_add_radio_actions(action_group, frameskip_entries, G_N_ELEMENTS(frameskip_entries), config.frameskip, G_CALLBACK(Modify_Frameskip), NULL); autoFrameskipMax = config.frameskip; gtk_toggle_action_set_active((GtkToggleAction*)gtk_action_group_get_action(action_group, "frameskipA"), config.autoframeskip); @@ -3485,7 +3543,7 @@ common_gtk_main( class configured_features *my_config) break; } nds_screen.rotation_angle = config.view_rot; - gtk_action_group_add_radio_actions(action_group, rotation_entries, G_N_ELEMENTS(rotation_entries), + gtk_action_group_add_radio_actions(action_group, rotation_entries, G_N_ELEMENTS(rotation_entries), nds_screen.rotation_angle, G_CALLBACK(SetRotation), NULL); @@ -3493,14 +3551,14 @@ common_gtk_main( class configured_features *my_config) config.window_scale = WINSIZE_SCALE; } winsize_current = (winsize_enum)config.window_scale.get(); - gtk_action_group_add_radio_actions(action_group, winsize_entries, G_N_ELEMENTS(winsize_entries), + gtk_action_group_add_radio_actions(action_group, winsize_entries, G_N_ELEMENTS(winsize_entries), winsize_current, G_CALLBACK(SetWinsize), NULL); if (config.view_orient < ORIENT_VERTICAL || config.view_orient > ORIENT_SINGLE) { config.view_orient = ORIENT_VERTICAL; } nds_screen.orientation = (orientation_enum)config.view_orient.get(); - gtk_action_group_add_radio_actions(action_group, orientation_entries, G_N_ELEMENTS(orientation_entries), + gtk_action_group_add_radio_actions(action_group, orientation_entries, G_N_ELEMENTS(orientation_entries), nds_screen.orientation, G_CALLBACK(SetOrientation), NULL); { @@ -3521,7 +3579,7 @@ common_gtk_main( class configured_features *my_config) gtk_toggle_action_set_active((GtkToggleAction*)gtk_action_group_get_action(action_group, "orient_swapscreens"), config.view_swap); gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - + accel_group = gtk_ui_manager_get_accel_group (ui_manager); gtk_window_add_accel_group (GTK_WINDOW (pWindow), accel_group); @@ -3608,22 +3666,60 @@ common_gtk_main( class configured_features *my_config) gtk_toggle_action_set_active((GtkToggleAction *)action, FALSE); } -#if defined(HAVE_OPENGL) && defined(OGLRENDER_3_2_H) +#if defined(ENABLE_OPENGL_STANDARD) || defined(ENABLE_OPENGL_ES) + #if defined(OGLRENDER_3_2_H) OGLLoadEntryPoints_3_2_Func = OGLLoadEntryPoints_3_2; OGLCreateRenderer_3_2_Func = OGLCreateRenderer_3_2; -#endif + #endif + #if defined(OGLRENDER_ES3_H) + OGLLoadEntryPoints_ES_3_0_Func = &OGLLoadEntryPoints_ES_3_0; + OGLCreateRenderer_ES_3_0_Func = &OGLCreateRenderer_ES_3_0; + #endif + + #if defined(ENABLE_GLX) + oglrender_init = &glx_initOpenGL_StandardAuto; + oglrender_deinit = &glx_deinitOpenGL; + oglrender_beginOpenGL = &glx_beginOpenGL; + oglrender_endOpenGL = &glx_endOpenGL; + oglrender_framebufferDidResizeCallback = &glx_framebufferDidResizeCallback; + #elif defined(ENABLE_OSMESA) + oglrender_init = &osmesa_initOpenGL_StandardAuto; + oglrender_deinit = &osmesa_deinitOpenGL; + oglrender_beginOpenGL = &osmesa_beginOpenGL; + oglrender_endOpenGL = &osmesa_endOpenGL; + oglrender_framebufferDidResizeCallback = &osmesa_framebufferDidResizeCallback; + #elif defined(ENABLE_EGL) + oglrender_init = &egl_initOpenGL_StandardAuto; + oglrender_deinit = &egl_deinitOpenGL; + oglrender_beginOpenGL = &egl_beginOpenGL; + oglrender_endOpenGL = &egl_endOpenGL; + oglrender_framebufferDidResizeCallback = &egl_framebufferDidResizeCallback; + #else + oglrender_init = &sdl_initOpenGL_StandardAuto; + oglrender_deinit = &sdl_deinitOpenGL; + oglrender_beginOpenGL = &sdl_beginOpenGL; + oglrender_endOpenGL = &sdl_endOpenGL; + oglrender_framebufferDidResizeCallback = &sdl_framebufferDidResizeCallback; + #endif +#endif // ENABLE_OPENGL_STANDARD || ENABLE_OPENGL_ES //Set the 3D emulation to use int core = my_config->engine_3d; // setup the gdk 3D emulation; // Check if commandLine argument was passed or not - if (core == -1) { + if (core == -1) + { // If it was not passed, then get the Renderer config from the file core = config.core3D; // Check if it is valid - if (!(core >= 0 && core <= 2)) { +#if defined(ENABLE_OPENGL_ES) + if (!(core >= 0 && core <= 2)) +#elif defined(ENABLE_OPENGL_STANDARD) + if (!(core >= 0 && core <= 4)) +#endif + { // If it is invalid, reset it to SoftRasterizer core = 1; } @@ -3631,21 +3727,65 @@ common_gtk_main( class configured_features *my_config) my_config->engine_3d = core; } - if (core == 2) + switch (core) { -#if !defined(HAVE_OPENGL) - core = RENDERID_SOFTRASTERIZER; -#elif defined(HAVE_LIBOSMESA) - if (!is_osmesa_initialized()) - { - init_osmesa_3Demu(); - } -#else - if (!is_sdl_initialized()) +#if defined(ENABLE_OPENGL_ES) && !defined(ENABLE_OSMESA) && !defined(ENABLE_GLX) + case 2: + #if defined(ENABLE_EGL) + oglrender_init = &egl_initOpenGL_ES_3_0; + #else + oglrender_init = &sdl_initOpenGL_ES_3_0; + #endif + break; +#elif defined(ENABLE_OPENGL_STANDARD) + case 2: + #if defined(ENABLE_GLX) + oglrender_init = &glx_initOpenGL_StandardAuto; + #elif defined(ENABLE_OSMESA) + oglrender_init = &osmesa_initOpenGL_StandardAuto; + #elif defined(ENABLE_EGL) + oglrender_init = &egl_initOpenGL_StandardAuto; + #else + oglrender_init = &sdl_initOpenGL_StandardAuto; + #endif + break; + + case 3: + #if defined(ENABLE_GLX) + oglrender_init = &glx_initOpenGL_LegacyAuto; + #elif defined(ENABLE_OSMESA) + oglrender_init = &osmesa_initOpenGL_LegacyAuto; + #elif defined(ENABLE_EGL) + oglrender_init = &egl_initOpenGL_LegacyAuto; + #else + oglrender_init = &sdl_initOpenGL_LegacyAuto; + #endif + break; + + case 4: + #if defined(ENABLE_GLX) + oglrender_init = &glx_initOpenGL_3_2_CoreProfile; + #elif defined(ENABLE_OSMESA) + oglrender_init = &osmesa_initOpenGL_3_2_CoreProfile; + #elif defined(ENABLE_EGL) + oglrender_init = &egl_initOpenGL_3_2_CoreProfile; + #else + oglrender_init = &sdl_initOpenGL_3_2_CoreProfile; + #endif + break; +#endif + default: { - init_sdl_3Demu(); + if (core > 0) + { + core = RENDERID_SOFTRASTERIZER; + } + else + { + core = RENDERID_NULL; + } + break; } -#endif } if (!GPU->Change3DRendererByID(core)) { @@ -3667,7 +3807,7 @@ common_gtk_main( class configured_features *my_config) backup_setManualBackupType(my_config->savetype); - // Command line arg + // Command line arg if( my_config->nds_file != "") { if(Open( my_config->nds_file.c_str()) >= 0) { my_config->process_movieCommands(); @@ -3715,11 +3855,17 @@ common_gtk_main( class configured_features *my_config) desmume_free(); -#if defined(HAVE_LIBOSMESA) - deinit_osmesa_3Demu(); -#else - deinit_sdl_3Demu(); -#endif +#if defined(ENABLE_OPENGL_STANDARD) || defined(ENABLE_OPENGL_ES) + #if defined(ENABLE_GLX) + glx_deinitOpenGL(); + #elif defined(ENABLE_OSMESA) + osmesa_deinitOpenGL(); + #elif defined(ENABLE_EGL) + egl_deinitOpenGL(); + #else + sdl_deinitOpenGL(); + #endif +#endif // ENABLE_OPENGL_STANDARD || ENABLE_OPENGL_ES /* Unload joystick */ uninit_joy(); diff --git a/desmume/src/frontend/posix/gtk2/meson.build b/desmume/src/frontend/posix/gtk2/meson.build index 25aa124b8..8420302d2 100644 --- a/desmume/src/frontend/posix/gtk2/meson.build +++ b/desmume/src/frontend/posix/gtk2/meson.build @@ -4,21 +4,43 @@ dep_x11 = dependency('x11') gtk_dependencies = dependencies + [dep_gtk3, dep_x11] desmume_src = [ - 'avout_pipe_base.cpp', - 'avout_x264.cpp', - 'avout_flac.cpp', + '../shared/avout_flac.cpp', + '../shared/avout_pipe_base.cpp', + '../shared/avout_x264.cpp', + '../shared/ctrlssdl.cpp', + '../shared/sndsdl.cpp', 'config.cpp', 'desmume.cpp', 'dToolsList.cpp', 'tools/ioregsView.cpp', - '../shared/sndsdl.cpp', - '../shared/ctrlssdl.cpp', - 'osmesa_3Demu.cpp', - 'sdl_3Demu.cpp', 'cheatsGTK.cpp', 'main.cpp', ] +if get_option('glx') and dep_glx.found() + add_global_arguments('-DENABLE_GLX', language: ['c', 'cpp']) + dependencies += dep_glx + desmume_src += [ + '../shared/glx_3Demu.cpp', + ] +elif get_option('osmesa') and dep_osmesa.found() + add_global_arguments('-DENABLE_OSMESA', language: ['c', 'cpp']) + dependencies += dep_osmesa + desmume_src += [ + '../shared/osmesa_3Demu.cpp', + ] +elif get_option('egl') and dep_egl.found() + add_global_arguments('-DENABLE_EGL', language: ['c', 'cpp']) + dependencies += dep_egl + desmume_src += [ + '../shared/egl_3Demu.cpp', + ] +else + desmume_src += [ + '../shared/sdl_3Demu.cpp', + ] +endif + # TODO: why do we have to redeclare it here with one more fs level? includes = include_directories( '../../../../src', diff --git a/desmume/src/frontend/posix/gtk2/osmesa_3Demu.cpp b/desmume/src/frontend/posix/gtk2/osmesa_3Demu.cpp deleted file mode 100644 index 78bf89a2e..000000000 --- a/desmume/src/frontend/posix/gtk2/osmesa_3Demu.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - Copyright (C) 2009 Guillaume Duhamel - Copyright (C) 2009-2024 DeSmuME team - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the this software. If not, see . - */ - -#ifdef HAVE_LIBOSMESA - -#include -#include -#include "../OGLRender_3_2.h" - -#include "osmesa_3Demu.h" - -static void *buffer = NULL; -static OSMesaContext ctx = NULL; - -static bool osmesa_beginOpenGL(void) { return 1; } -static void osmesa_endOpenGL(void) { } -static bool osmesa_init(void) { return is_osmesa_initialized(); } - -void deinit_osmesa_3Demu (void) -{ - free(buffer); - buffer = NULL; - - OSMesaDestroyContext(ctx); - ctx = NULL; -} - -bool init_osmesa_3Demu(void) -{ -#if (((OSMESA_MAJOR_VERSION * 100) + OSMESA_MINOR_VERSION) >= 1102) && defined(OSMESA_CONTEXT_MAJOR_VERSION) - static const int attributes_3_2_core_profile[] = { - OSMESA_FORMAT, OSMESA_RGBA, - OSMESA_DEPTH_BITS, 24, - OSMESA_STENCIL_BITS, 8, - OSMESA_ACCUM_BITS, 0, - OSMESA_PROFILE, OSMESA_CORE_PROFILE, - OSMESA_CONTEXT_MAJOR_VERSION, 3, - OSMESA_CONTEXT_MINOR_VERSION, 2, - 0 }; - - ctx = OSMesaCreateContextAttribs(attributes_3_2_core_profile, NULL); - if (ctx == NULL) - { - printf("OSMesa: Could not create a 3.2 Core Profile context. Will attempt to create a 2.1 compatibility context...\n"); - - static const int attributes_2_1[] = { - OSMESA_FORMAT, OSMESA_RGBA, - OSMESA_DEPTH_BITS, 24, - OSMESA_STENCIL_BITS, 8, - OSMESA_ACCUM_BITS, 0, - OSMESA_PROFILE, OSMESA_COMPAT_PROFILE, - OSMESA_CONTEXT_MAJOR_VERSION, 2, - OSMESA_CONTEXT_MINOR_VERSION, 1, - 0 }; - - ctx = OSMesaCreateContextAttribs(attributes_2_1, NULL); - } -#endif - - if (ctx == NULL) - { - ctx = OSMesaCreateContextExt(OSMESA_RGBA, 24, 8, 0, NULL); - if (ctx == NULL) - { - printf("OSMesa: OSMesaCreateContextExt() failed!\n"); - return false; - } - } - - buffer = malloc(GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * sizeof(uint32_t)); - if (!buffer) - { - printf("OSMesa: Could not allocate enough memory for the context!\n"); - return false; - } - - if (!OSMesaMakeCurrent(ctx, buffer, GL_UNSIGNED_BYTE, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT)) - { - printf("OSMesa: OSMesaMakeCurrent() failed!\n"); - free(buffer); - return false; - } - - oglrender_init = osmesa_init; - oglrender_beginOpenGL = osmesa_beginOpenGL; - oglrender_endOpenGL = osmesa_endOpenGL; - - return true; -} - -bool is_osmesa_initialized(void) -{ - return (ctx != NULL); -} - -#endif diff --git a/desmume/src/frontend/posix/gtk2/sdl_3Demu.cpp b/desmume/src/frontend/posix/gtk2/sdl_3Demu.cpp deleted file mode 100644 index fb05b157c..000000000 --- a/desmume/src/frontend/posix/gtk2/sdl_3Demu.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - Copyright (C) 2020 Emmanuel Gil Peyrot - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with the this software. If not, see . - */ - -#include -#include -#include "../OGLRender.h" - -#include "sdl_3Demu.h" - -static bool sdl_beginOpenGL(void) { return 1; } -static void sdl_endOpenGL(void) { } -static bool sdl_init(void) { return is_sdl_initialized(); } - -static SDL_Window *win = NULL; -static SDL_GLContext ctx = NULL; - -bool deinit_sdl_3Demu(void) -{ - bool ret = false; - - if (ctx) { - SDL_GL_DeleteContext(ctx); - ctx = NULL; - ret = true; - } - - if (win) { - SDL_DestroyWindow(win); - win = NULL; - ret = true; - } - - return ret; -} - -bool init_sdl_3Demu(void) -{ - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); - SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); - - win = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 256, 192, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN); - if (!win) { - fprintf(stderr, "SDL: Failed to create a window: %s\n", SDL_GetError()); - return false; - } - - ctx = SDL_GL_CreateContext(win); - if (!ctx) { - fprintf(stderr, "SDL: Failed to create an OpenGL context: %s\n", SDL_GetError()); - return false; - } - - printf("OGL/SDL Renderer has finished the initialization.\n"); - - oglrender_init = sdl_init; - oglrender_beginOpenGL = sdl_beginOpenGL; - oglrender_endOpenGL = sdl_endOpenGL; - - return true; -} - -bool is_sdl_initialized(void) -{ - return (ctx != NULL); -} diff --git a/desmume/src/frontend/posix/meson.build b/desmume/src/frontend/posix/meson.build index 13bf45a25..3280842b4 100644 --- a/desmume/src/frontend/posix/meson.build +++ b/desmume/src/frontend/posix/meson.build @@ -16,11 +16,15 @@ dep_pcap = dependency('pcap') dep_zlib = dependency('zlib') dep_threads = dependency('threads') dep_gl = dependency('gl', required: false) +dep_gles = dependency('glesv2', required: false) dep_openal = dependency('openal', required: get_option('openal')) dep_alsa = dependency('alsa', required: false) dep_soundtouch = dependency('soundtouch', required: false) dep_agg = dependency('libagg', required: false) dep_fontconfig = dependency('fontconfig', required: false) +dep_glx = dependency('glx', required: false) +dep_osmesa = dependency('osmesa', required: false) +dep_egl = dependency('egl', required: false) # XXX: something wrong with this one. #dep_lua = dependency('lua-5.1', required: false) @@ -168,12 +172,65 @@ libdesmume_src += [ 'shared/desmume_config.cpp', ] -if dep_gl.found() - dependencies += dep_gl - libdesmume_src += [ - '../../OGLRender.cpp', - '../../OGLRender_3_2.cpp', - ] +if get_option('opengles') + if dep_gles.found() + add_global_arguments('-DENABLE_OPENGL_ES', language: ['c', 'cpp']) + dependencies += dep_gles + libdesmume_src += [ + '../../OGLRender.cpp', + '../../OGLRender_3_2.cpp', + '../../OGLRender_ES3.cpp', + ] + else + message('Cannot build with OpenGL ES -- glesv2 library not found.') + endif +elif get_option('opengl') + if dep_gl.found() + add_global_arguments('-DENABLE_OPENGL_STANDARD', language: ['c', 'cpp']) + dependencies += dep_gl + libdesmume_src += [ + '../../OGLRender.cpp', + '../../OGLRender_3_2.cpp', + ] + else + message('Cannot build with OpenGL -- gl library not found.') + endif +endif + +if get_option('glx') + if dep_glx.found() + if get_option('opengl') and dep_gl.found() + add_global_arguments('-DENABLE_GLX', language: ['c', 'cpp']) + dependencies += dep_glx + elif get_option('opengles') + message('GLX contexts are incompatible with OpenGL ES -- cancelling the use of GLX.') + else + message('GLX contexts are only compatible with standard OpenGL -- cancelling the use of GLX.') + endif + else + message('Cannot use GLX -- glx library not found.') + endif +elif get_option('osmesa') + if dep_osmesa.found() + if get_option('opengl') and dep_gl.found() + message('OSMesa contexts are deprecated.') + add_global_arguments('-DENABLE_OSMESA', language: ['c', 'cpp']) + dependencies += dep_osmesa + elif get_option('opengles') + message('OSMesa contexts are incompatible with OpenGL ES -- cancelling the use of OSMesa.') + else + message('OSMesa contexts are only compatible with standard OpenGL -- cancelling the use of OSMesa.') + endif + else + message('Cannot use OSMesa -- osmesa library not found.') + endif +elif get_option('egl') + if dep_egl.found() + add_global_arguments('-DENABLE_EGL', language: ['c', 'cpp']) + dependencies += dep_egl + else + message('Cannot use EGL -- egl library not found.') + endif endif if dep_openal.found() diff --git a/desmume/src/frontend/posix/meson_options.txt b/desmume/src/frontend/posix/meson_options.txt index 1deece7f0..bbe866a21 100644 --- a/desmume/src/frontend/posix/meson_options.txt +++ b/desmume/src/frontend/posix/meson_options.txt @@ -1,3 +1,28 @@ +option('opengl', + type: 'boolean', + value: false, + description: 'Build for OpenGL', +) +option('opengles', + type: 'boolean', + value: false, + description: 'Build for OpenGL ES', +) +option('glx', + type: 'boolean', + value: false, + description: 'Use a GLX context', +) +option('osmesa', + type: 'boolean', + value: false, + description: 'Use a OSMesa context', +) +option('egl', + type: 'boolean', + value: false, + description: 'Use a EGL context', +) option('openal', type: 'boolean', value: false, diff --git a/desmume/src/frontend/posix/gtk/avout.h b/desmume/src/frontend/posix/shared/avout.h similarity index 100% rename from desmume/src/frontend/posix/gtk/avout.h rename to desmume/src/frontend/posix/shared/avout.h diff --git a/desmume/src/frontend/posix/gtk/avout_flac.cpp b/desmume/src/frontend/posix/shared/avout_flac.cpp similarity index 100% rename from desmume/src/frontend/posix/gtk/avout_flac.cpp rename to desmume/src/frontend/posix/shared/avout_flac.cpp diff --git a/desmume/src/frontend/posix/gtk/avout_flac.h b/desmume/src/frontend/posix/shared/avout_flac.h similarity index 100% rename from desmume/src/frontend/posix/gtk/avout_flac.h rename to desmume/src/frontend/posix/shared/avout_flac.h diff --git a/desmume/src/frontend/posix/gtk/avout_pipe_base.cpp b/desmume/src/frontend/posix/shared/avout_pipe_base.cpp similarity index 100% rename from desmume/src/frontend/posix/gtk/avout_pipe_base.cpp rename to desmume/src/frontend/posix/shared/avout_pipe_base.cpp diff --git a/desmume/src/frontend/posix/gtk/avout_pipe_base.h b/desmume/src/frontend/posix/shared/avout_pipe_base.h similarity index 100% rename from desmume/src/frontend/posix/gtk/avout_pipe_base.h rename to desmume/src/frontend/posix/shared/avout_pipe_base.h diff --git a/desmume/src/frontend/posix/gtk/avout_x264.cpp b/desmume/src/frontend/posix/shared/avout_x264.cpp similarity index 100% rename from desmume/src/frontend/posix/gtk/avout_x264.cpp rename to desmume/src/frontend/posix/shared/avout_x264.cpp diff --git a/desmume/src/frontend/posix/gtk/avout_x264.h b/desmume/src/frontend/posix/shared/avout_x264.h similarity index 100% rename from desmume/src/frontend/posix/gtk/avout_x264.h rename to desmume/src/frontend/posix/shared/avout_x264.h diff --git a/desmume/src/frontend/posix/shared/egl_3Demu.cpp b/desmume/src/frontend/posix/shared/egl_3Demu.cpp new file mode 100644 index 000000000..f15e2b428 --- /dev/null +++ b/desmume/src/frontend/posix/shared/egl_3Demu.cpp @@ -0,0 +1,357 @@ +/* + Copyright (C) 2024 DeSmuME team + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the this software. If not, see . +*/ + +#include +#include +#include +#include + +#include "egl_3Demu.h" +#include "OGLRender_3_2.h" + + +static EGLDisplay currDisplay = EGL_NO_DISPLAY; +static EGLSurface currSurface = EGL_NO_SURFACE; +static EGLContext currContext = EGL_NO_CONTEXT; + +static EGLDisplay prevDisplay = EGL_NO_DISPLAY; +static EGLSurface prevDrawSurface = EGL_NO_SURFACE; +static EGLSurface prevReadSurface = EGL_NO_SURFACE; +static EGLContext prevContext = EGL_NO_CONTEXT; + +static EGLSurface pendingSurface = EGL_NO_SURFACE; +static EGLint *lastConfigAttr = NULL; + +static bool __egl_initOpenGL(const int requestedAPI, const int requestedProfile, const int requestedVersionMajor, const int requestedVersionMinor) +{ + if (currContext != EGL_NO_CONTEXT) + { + return true; + } + + EGLint eglMajorVersion; + EGLint eglMinorVersion; + + currDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (eglInitialize(currDisplay, &eglMajorVersion, &eglMinorVersion) == EGL_FALSE) + { + puts("EGL: eglInitialize failed"); + return false; + } + + // Our EGL context requires the following features: + // - EGL_OPENGL_ES3_BIT for EGL_RENDERABLE_TYPE + // - EGL_KHR_surfaceless_context + if ( (eglMajorVersion <= 1) && (eglMinorVersion < 5) ) + { + if (eglMinorVersion < 4) + { + eglTerminate(currDisplay); + printf("EGL: Requires EGL v1.4 or later. Your EGL version (v%i.%i) is too old.\n", (int)eglMajorVersion, (int)eglMinorVersion); + return false; + } + + const char *extensionSet = eglQueryString(currDisplay, EGL_EXTENSIONS); + + const char *foundString = strstr(extensionSet, "EGL_KHR_create_context"); + if (foundString == NULL) + { + eglTerminate(currDisplay); + puts("EGL: OpenGL ES 3.0 context creation is not available."); + return false; + } + + foundString = strstr(extensionSet, "EGL_KHR_surfaceless_context"); + if (foundString == NULL) + { + eglTerminate(currDisplay); + puts("EGL: EGL_KHR_surfaceless_context is a required extension."); + return false; + } + } + + // EGL config attributes, initially set up for standard OpenGL running in legacy mode + EGLint confAttr[] = { + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, + EGL_DEPTH_SIZE, 24, + EGL_STENCIL_SIZE, 8, + EGL_NONE + }; + + if ( (requestedAPI == EGL_OPENGL_API) && (requestedProfile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR) ) + { + confAttr[8] = EGL_NONE; + confAttr[9] = EGL_NONE; + + confAttr[10] = EGL_NONE; + confAttr[11] = EGL_NONE; + + confAttr[12] = EGL_NONE; + confAttr[13] = EGL_NONE; + } + else if (requestedAPI == EGL_OPENGL_ES_API) + { + confAttr[8] = EGL_RENDERABLE_TYPE; + confAttr[9] = EGL_OPENGL_ES3_BIT_KHR; + + confAttr[10] = EGL_NONE; + confAttr[11] = EGL_NONE; + + confAttr[12] = EGL_NONE; + confAttr[13] = EGL_NONE; + } + + // choose the first config, i.e. best config + EGLConfig eglConf; + EGLint numConfigs; + eglChooseConfig(currDisplay, confAttr, &eglConf, 1, &numConfigs); + if (numConfigs < 1) + { + eglTerminate(currDisplay); + puts("EGL: eglChooseConfig failed"); + return false; + } + + // Make a copy of the last working config attributes for legacy OpenGL running + // the default framebuffer. + if (lastConfigAttr == NULL) + { + lastConfigAttr = (EGLint *)malloc(sizeof(confAttr)); + } + memcpy(lastConfigAttr, confAttr, sizeof(confAttr)); + + eglBindAPI(requestedAPI); + + // EGL context attributes + const EGLint ctxAttr[] = { + EGL_CONTEXT_MAJOR_VERSION_KHR, requestedVersionMajor, + EGL_CONTEXT_MINOR_VERSION_KHR, requestedVersionMinor, + (requestedAPI == EGL_OPENGL_ES_API) ? EGL_NONE : EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, requestedProfile, + EGL_NONE + }; + + currContext = eglCreateContext(currDisplay, eglConf, EGL_NO_CONTEXT, ctxAttr); + if (currContext == EGL_NO_CONTEXT) + { + eglTerminate(currDisplay); + puts("EGL: eglCreateContext failed"); + return false; + } + + if (requestedProfile == EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR) + { + // Do note that P-Buffer creation has to occur after context creation + // since P-Buffers are dependent on a context with EGL_PBUFFER_BIT as + // its EGL_SURFACE_TYPE. + const EGLint pbufferAttr[] = { + EGL_WIDTH, (EGLint)GPU_FRAMEBUFFER_NATIVE_WIDTH, + EGL_HEIGHT, (EGLint)GPU_FRAMEBUFFER_NATIVE_HEIGHT, + EGL_NONE + }; + + currSurface = eglCreatePbufferSurface(currDisplay, eglConf, pbufferAttr); + if (currSurface == EGL_NO_SURFACE) + { + puts("EGL: eglCreatePbufferSurface failed"); + return false; + } + } + + puts("EGL: OpenGL context creation successful."); + return true; +} + +bool egl_initOpenGL_StandardAuto() +{ + bool isContextCreated = egl_initOpenGL_3_2_CoreProfile(); + + if (!isContextCreated) + { + isContextCreated = egl_initOpenGL_LegacyAuto(); + } + + return isContextCreated; +} + +bool egl_initOpenGL_LegacyAuto() +{ + return __egl_initOpenGL(EGL_OPENGL_API, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR, 1, 2); +} + +bool egl_initOpenGL_3_2_CoreProfile() +{ + return __egl_initOpenGL(EGL_OPENGL_API, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR, 3, 2); +} + +bool egl_initOpenGL_ES_3_0() +{ + return __egl_initOpenGL(EGL_OPENGL_ES_API, EGL_NONE, 3, 0); +} + +void egl_deinitOpenGL() +{ + if (currDisplay == EGL_NO_DISPLAY) + { + return; + } + + eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroyContext(currDisplay, currContext); + + if (currSurface != EGL_NO_SURFACE) + { + eglDestroySurface(currDisplay, currSurface); + } + + eglTerminate(currDisplay); + + if (lastConfigAttr == NULL) + { + free(lastConfigAttr); + lastConfigAttr = NULL; + } + + currContext = EGL_NO_CONTEXT; + currSurface = EGL_NO_SURFACE; + currDisplay = EGL_NO_DISPLAY; + + prevDisplay = EGL_NO_DISPLAY; + prevDrawSurface = EGL_NO_SURFACE; + prevReadSurface = EGL_NO_SURFACE; + prevContext = EGL_NO_CONTEXT; +} + +bool egl_beginOpenGL() +{ + EGLBoolean ret = EGL_FALSE; + + prevDisplay = eglGetCurrentDisplay(); + prevDrawSurface = eglGetCurrentSurface(0); + prevReadSurface = eglGetCurrentSurface(1); + prevContext = eglGetCurrentContext(); + + if (pendingSurface != EGL_NO_SURFACE) + { + bool previousIsCurrent = (prevDrawSurface == currSurface); + + ret = eglMakeCurrent(currDisplay, pendingSurface, pendingSurface, currContext); + if (ret == EGL_TRUE) + { + eglDestroySurface(currDisplay, currSurface); + currSurface = pendingSurface; + + if (previousIsCurrent) + { + prevDrawSurface = currSurface; + prevReadSurface = currSurface; + } + + pendingSurface = EGL_NO_SURFACE; + } + } + else + { + ret = eglMakeCurrent(currDisplay, currSurface, currSurface, currContext); + } + + return (ret == EGL_TRUE); +} + +void egl_endOpenGL() +{ + if (prevDisplay == EGL_NO_DISPLAY) + { + prevDisplay = currDisplay; + } + + if (prevContext == EGL_NO_CONTEXT) + { + prevContext = currContext; + } + + if (prevDrawSurface == EGL_NO_SURFACE) + { + prevDrawSurface = currSurface; + } + + if (prevReadSurface == EGL_NO_SURFACE) + { + prevReadSurface = currSurface; + } + + if ( (prevDisplay != currDisplay) || + (prevContext != currContext) || + (prevDrawSurface != currSurface) || + (prevReadSurface != currSurface) ) + { + eglMakeCurrent(prevDisplay, prevDrawSurface, prevReadSurface, prevContext); + } +} + +bool egl_framebufferDidResizeCallback(bool isFBOSupported, size_t w, size_t h) +{ + bool result = false; + + if (isFBOSupported) + { + result = true; + return result; + } + + EGLint currWidth; + EGLint currHeight; + eglQuerySurface(currDisplay, currSurface, EGL_WIDTH, &currWidth); + eglQuerySurface(currDisplay, currSurface, EGL_HEIGHT, &currHeight); + + if ( (w == (size_t)currWidth) && (h == (size_t)currHeight) ) + { + result = true; + return result; + } + + if (pendingSurface != EGL_NO_SURFACE) + { + // Destroy any existing pending surface now since we need it to + // always have the lastest framebuffer size. + eglDestroySurface(currDisplay, pendingSurface); + } + + // choose the first config, i.e. best config + EGLConfig eglConf; + EGLint numConfigs; + eglChooseConfig(currDisplay, lastConfigAttr, &eglConf, 1, &numConfigs); + + const EGLint pbufferAttr[] = { + EGL_WIDTH, (EGLint)w, + EGL_HEIGHT, (EGLint)h, + EGL_NONE + }; + + pendingSurface = eglCreatePbufferSurface(currDisplay, eglConf, pbufferAttr); + if (pendingSurface == EGL_NO_SURFACE) + { + puts("EGL: eglCreatePbufferSurface failed"); + return result; + } + + result = true; + return result; +} diff --git a/desmume/src/frontend/posix/gtk2/avout_x264.h b/desmume/src/frontend/posix/shared/egl_3Demu.h similarity index 61% rename from desmume/src/frontend/posix/gtk2/avout_x264.h rename to desmume/src/frontend/posix/shared/egl_3Demu.h index 24125a0f9..b9775516c 100644 --- a/desmume/src/frontend/posix/gtk2/avout_x264.h +++ b/desmume/src/frontend/posix/shared/egl_3Demu.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 DeSmuME team + Copyright (C) 2024 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,20 +15,17 @@ along with the this software. If not, see . */ -#ifndef _AVOUT_X264_H_ -#define _AVOUT_X264_H_ +#ifndef __EGL_3DEMU_H__ +#define __EGL_3DEMU_H__ -#include "avout_pipe_base.h" +bool egl_initOpenGL_StandardAuto(); +bool egl_initOpenGL_LegacyAuto(); +bool egl_initOpenGL_3_2_CoreProfile(); +bool egl_initOpenGL_ES_3_0(); -class AVOutX264 : public AVOutPipeBase { -public: - AVOutX264(); -protected: - Type type() { return TYPE_VIDEO; } - const char* const* getArgv(const char* fname); -private: - char filename[1024]; - const char* args[19]; -}; +void egl_deinitOpenGL(); +bool egl_beginOpenGL(); +void egl_endOpenGL(); +bool egl_framebufferDidResizeCallback(bool isFBOSupported, size_t w, size_t h); -#endif +#endif // __EGL_3DEMU_H__ diff --git a/desmume/src/frontend/posix/shared/glx_3Demu.cpp b/desmume/src/frontend/posix/shared/glx_3Demu.cpp new file mode 100644 index 000000000..71b3dee2a --- /dev/null +++ b/desmume/src/frontend/posix/shared/glx_3Demu.cpp @@ -0,0 +1,370 @@ +/* + Copyright (C) 2024 DeSmuME team + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the this software. If not, see . +*/ + +#include +#include +#include +#include +#include +#include + +#include "glx_3Demu.h" + + +static Display *currDisplay = NULL; +static GLXDrawable currDrawable = 0; +static GLXContext currContext = NULL; + +static Display *prevDisplay = NULL; +static GLXDrawable prevDrawDrawable = 0; +static GLXDrawable prevReadDrawable = 0; +static GLXContext prevContext = NULL; + +static GLXDrawable pendingDrawable = 0; + +static GLXFBConfig bestFBConfig = NULL; + +static bool didErrorOccur = false; + +static int __GLXContextErrorHandler(Display *dpy, XErrorEvent *ev) +{ + didErrorOccur = true; + return 0; +} + +static void __GLXCurrentDisplayClose() +{ + if (currDisplay == NULL) + { + return; + } + + XCloseDisplay(currDisplay); + currDisplay = NULL; +} + +static bool __glx_initOpenGL(const int requestedProfile, const int requestedVersionMajor, const int requestedVersionMinor) +{ + if (currContext != NULL) + { + return true; + } + + currDisplay = XOpenDisplay(NULL); + + int currScreen = DefaultScreen(currDisplay); + int glxMajorVersion = 0; + int glxMinorVersion = 0; + + if (glXQueryVersion(currDisplay, &glxMajorVersion, &glxMinorVersion) == False) + { + __GLXCurrentDisplayClose(); + puts("GLX: glXQueryVersion failed"); + return false; + } + + // Our GLX context requires the following features: + // - GLX_ARB_create_context_profile + PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = NULL; + + if ( (glxMajorVersion >= 2) || ((glxMajorVersion == 1) && (glxMinorVersion >= 4)) ) + { + const char *extensionSet = glXQueryExtensionsString(currDisplay, currScreen); + + const char *foundString = strstr(extensionSet, "GLX_ARB_create_context_profile"); + glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB"); + + if ( (foundString == NULL) || (glXCreateContextAttribsARB == NULL) ) + { + __GLXCurrentDisplayClose(); + puts("GLX: OpenGL context creation is not available."); + return false; + } + } + else + { + __GLXCurrentDisplayClose(); + printf("GLX: Requires GLX v1.4 or later. Your GLX version (v%i.%i) is too old.\n", (int)glxMajorVersion, (int)glxMinorVersion); + return false; + } + + // Begin the process of searching for the best framebuffer configuration. + // This will be needed for creating the context and other related things. + int fbConfigAttr[] = { + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, + GLX_DEPTH_SIZE, 24, + GLX_STENCIL_SIZE, 8, + 0 + }; + + if (requestedProfile == GLX_CONTEXT_CORE_PROFILE_BIT_ARB) + { + // 3.2 Core Profile always uses FBOs, and so no P-Buffers, depth + // buffers, or stencil buffers are needed for this kind of context. + confAttr[10] = 0; + confAttr[11] = 0; + + confAttr[12] = 0; + confAttr[13] = 0; + + confAttr[14] = 0; + confAttr[15] = 0; + } + + int fbConfigCount = 0; + GLXFBConfig *fbConfigList = glXChooseFBConfig(currDisplay, currScreen, fbConfigAttr, &fbConfigCount); + if ( (fbConfigList == NULL) || (fbConfigCount < 1) ) + { + __GLXCurrentDisplayClose(); + puts("GLX: glXChooseFBConfig found no configs"); + return false; + } + + int bestFBConfigIndex = -1; + int bestNumSamples = -1; + int configHasMultisamples = 0; + int numSamples = 0; + + // Discover the best framebuffer config for multisampled rendering on the + // default framebuffer. This isn't needed if we're running FBOs, but is + // needed for legacy OpenGL without FBO support. + for (int i = 0; i < fbConfigCount; i++) + { + XVisualInfo *vi = glXGetVisualFromFBConfig(currDisplay, fbConfigList[i]); + + if (vi != NULL) + { + glXGetFBConfigAttrib(currDisplay, fbConfigList[i], GLX_SAMPLE_BUFFERS, &configHasMultisamples); + glXGetFBConfigAttrib(currDisplay, fbConfigList[i], GLX_SAMPLES, &numSamples); + + if ( ((bestFBConfigIndex < 0) || configHasMultisamples) && (numSamples > bestNumSamples) ) + { + bestFBConfigIndex = i; + bestNumSamples = numSamples; + } + + XFree(vi); + } + } + + bestFBConfig = fbConfigList[bestFBConfigIndex]; + XFree(fbConfigList); + + if (requestedProfile == GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB) + { + const int pbufferAttr[] = { + GLX_PBUFFER_WIDTH, 256, + GLX_PBUFFER_HEIGHT, 192, + 0 + }; + + currDrawable = glXCreatePbuffer(currDisplay, bestFBConfig, pbufferAttr); + } + + // Install an X error handler so the application won't exit if GL 3.0 + // context allocation fails. + // + // Note this error handler is global. All display connections in all threads + // of a process use the same error handler, so be sure to guard against other + // threads issuing X commands while this code is running. + didErrorOccur = false; + int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&__GLXContextErrorHandler); + + // GLX context attributes + const int ctxAttr[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, requestedVersionMajor, + GLX_CONTEXT_MINOR_VERSION_ARB, requestedVersionMinor, + GLX_CONTEXT_PROFILE_MASK_ARB, requestedProfile, + 0 + }; + + currContext = glXCreateContextAttribsARB(currDisplay, bestFBConfig, NULL, True, ctxAttr); + + XSync(currDisplay, False); // Sync to ensure any errors generated are processed. + XSetErrorHandler(oldHandler); // Restore the original error handler + + if (didErrorOccur || (currContext == NULL)) + { + __GLXCurrentDisplayClose(); + puts("GLX: glXCreateContextAttribsARB failed"); + return false; + } + + puts("GLX: OpenGL context creation successful."); + return true; +} + +bool glx_initOpenGL_StandardAuto() +{ + bool isContextCreated = glx_initOpenGL_3_2_CoreProfile(); + + if (!isContextCreated) + { + isContextCreated = glx_initOpenGL_LegacyAuto(); + } + + return isContextCreated; +} + +bool glx_initOpenGL_LegacyAuto() +{ + return __glx_initOpenGL(GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 1, 2); +} + +bool glx_initOpenGL_3_2_CoreProfile() +{ + return __glx_initOpenGL(GLX_CONTEXT_CORE_PROFILE_BIT_ARB, 3, 2); +} + +void glx_deinitOpenGL() +{ + if (currDrawable != 0) + { + glXDestroyPbuffer(currDisplay, currDrawable); + currDrawable = 0; + } + + if (pendingDrawable != 0) + { + glXDestroyPbuffer(currDisplay, pendingDrawable); + pendingDrawable = 0; + } + + if ( (currDisplay != NULL) && (currContext != NULL) ) + { + glXMakeContextCurrent(currDisplay, 0, 0, NULL); + glXDestroyContext(currDisplay, currContext); + currContext = NULL; + + __GLXCurrentDisplayClose(); + } + + prevDisplay = NULL; + prevDrawDrawable = 0; + prevReadDrawable = 0; + prevContext = NULL; +} + +bool glx_beginOpenGL() +{ + Bool ret = False; + + prevDisplay = glXGetCurrentDisplay(); + prevDrawDrawable = glXGetCurrentDrawable(); + prevReadDrawable = glXGetCurrentReadDrawable(); + prevContext = glXGetCurrentContext(); + + if (pendingDrawable != NULL) + { + bool previousIsCurrent = (prevDrawDrawable == currDrawable); + + ret = glXMakeContextCurrent(currDisplay, pendingDrawable, pendingDrawable, currContext); + if (ret == True) + { + glXDestroyPbuffer(currDisplay, currDrawable); + currDrawable = pendingDrawable; + + if (previousIsCurrent) + { + prevDrawDrawable = currDrawable; + prevReadDrawable = currDrawable; + } + + pendingDrawable = 0; + } + } + else + { + ret = glXMakeContextCurrent(currDisplay, currDrawable, currDrawable, currContext); + } + + return (ret == True); +} + +void glx_endOpenGL() +{ + if (prevDisplay == NULL) + { + prevDisplay = currDisplay; + } + + if (prevContext == NULL) + { + prevContext = currContext; + } + + if (prevDrawDrawable == 0) + { + prevDrawDrawable = currDrawable; + } + + if (prevReadDrawable == 0) + { + prevReadDrawable = currDrawable; + } + + if ( (prevDisplay != currDisplay) || + (prevContext != currContext) || + (prevDrawDrawable != currDrawable) || + (prevReadDrawable != currDrawable) ) + { + glXMakeContextCurrent(prevDisplay, prevDrawDrawable, prevReadDrawable, prevContext); + } +} + +bool glx_framebufferDidResizeCallback(bool isFBOSupported, size_t w, size_t h) +{ + bool result = false; + + if (isFBOSupported) + { + result = true; + return result; + } + + unsigned int currWidth; + unsigned int currHeight; + glXQueryDrawable(currDisplay, currDrawable, GLX_WIDTH, &currWidth); + glXQueryDrawable(currDisplay, currDrawable, GLX_HEIGHT, &currHeight); + + if ( (w == (size_t)currWidth) && (h == (size_t)currHeight) ) + { + result = true; + return result; + } + + if (pendingDrawable != 0) + { + glXDestroyPbuffer(currDisplay, pendingDrawable); + } + + const int pbufferAttr[] = { + GLX_PBUFFER_WIDTH, (int)w, + GLX_PBUFFER_HEIGHT, (int)h, + 0 + }; + + pendingDrawable = glXCreatePbuffer(currDisplay, bestFBConfig, pbufferAttr); + + result = true; + return result; +} diff --git a/desmume/src/frontend/posix/gtk2/avout.h b/desmume/src/frontend/posix/shared/glx_3Demu.h similarity index 63% rename from desmume/src/frontend/posix/gtk2/avout.h rename to desmume/src/frontend/posix/shared/glx_3Demu.h index 8966856ea..2111dc6b5 100644 --- a/desmume/src/frontend/posix/gtk2/avout.h +++ b/desmume/src/frontend/posix/shared/glx_3Demu.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 DeSmuME team + Copyright (C) 2024 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,18 +15,16 @@ along with the this software. If not, see . */ -#ifndef _AVOUT_H_ -#define _AVOUT_H_ +#ifndef __GLX_3DEMU_H__ +#define __GLX_3DEMU_H__ -#include "types.h" +bool glx_initOpenGL_StandardAuto(); +bool glx_initOpenGL_LegacyAuto(); +bool glx_initOpenGL_3_2_CoreProfile(); -class AVOut { -public: - virtual bool begin(const char* fname) { return false; } - virtual void end() {} - virtual bool isRecording() { return false; } - virtual void updateAudio(void* soundData, int soundLen) {} - virtual void updateVideo(const u16* buffer) {} -}; +void glx_deinitOpenGL(); +bool glx_beginOpenGL(); +void glx_endOpenGL(); +bool glx_framebufferDidResizeCallback(bool isFBOSupported, size_t w, size_t h); -#endif +#endif // __GLX_3DEMU_H__ diff --git a/desmume/src/frontend/posix/shared/osmesa_3Demu.cpp b/desmume/src/frontend/posix/shared/osmesa_3Demu.cpp new file mode 100644 index 000000000..c3bb790e0 --- /dev/null +++ b/desmume/src/frontend/posix/shared/osmesa_3Demu.cpp @@ -0,0 +1,284 @@ +/* + Copyright (C) 2009 Guillaume Duhamel + Copyright (C) 2009-2024 DeSmuME team + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the this software. If not, see . + */ + +#include +#include + +#include "osmesa_3Demu.h" +#include "OGLRender_3_2.h" + +#warning OSMesa contexts are deprecated. + + +static OSMesaContext currContext = NULL; +static GLint currCtxFormat = GL_UNSIGNED_BYTE; +static GLint currCtxWidth = 0; +static GLint currCtxHeight = 0; +static void *currCtxBuffer = NULL; + +static OSMesaContext prevContext = NULL; +static GLint prevCtxFormat = GL_UNSIGNED_BYTE; +static GLint prevCtxWidth = 0; +static GLint prevCtxHeight = 0; +static void *prevCtxBuffer = NULL; + +static void *pendingCtxBuffer = NULL; +static GLint pendingCtxWidth = 0; +static GLint pendingCtxHeight = 0; + +static bool __osmesa_initOpenGL(const int requestedProfile, const int requestedVersionMajor, const int requestedVersionMinor) +{ + GLboolean ret = GL_FALSE; + + if (currContext != NULL) + { + return true; + } + +#if (((OSMESA_MAJOR_VERSION * 100) + OSMESA_MINOR_VERSION) >= 1102) && defined(OSMESA_CONTEXT_MAJOR_VERSION) + const int ctxAttributes[] = { + OSMESA_FORMAT, OSMESA_RGBA, + OSMESA_DEPTH_BITS, ( (requestedProfile == OSMESA_CORE_PROFILE) && ((requestedVersionMajor >= 4) || ((requestedVersionMajor == 3) && (requestedVersionMinor >= 2))) ) ? 0 : 24, + OSMESA_STENCIL_BITS, ( (requestedProfile == OSMESA_CORE_PROFILE) && ((requestedVersionMajor >= 4) || ((requestedVersionMajor == 3) && (requestedVersionMinor >= 2))) ) ? 0 : 8, + OSMESA_ACCUM_BITS, 0, + OSMESA_PROFILE, requestedProfile, + OSMESA_CONTEXT_MAJOR_VERSION, requestedVersionMajor, + OSMESA_CONTEXT_MINOR_VERSION, requestedVersionMinor, + 0 + }; + + currContext = OSMesaCreateContextAttribs(ctxAttributes, NULL); + if (currContext == NULL) + { + if (requestedProfile == OSMESA_CORE_PROFILE) + { + puts("OSMesa: OSMesaCreateContextAttribs() failed!"); + return false; + } + else if (requestedProfile == OSMESA_COMPAT_PROFILE) + { + puts("OSMesa: Could not create a context using OSMesaCreateContextAttribs(). Will attempt to use OSMesaCreateContextExt() instead..."); + } + } + + if ( (currContext == NULL) && (requestedProfile == OSMESA_COMPAT_PROFILE) ) +#endif + { + currContext = OSMesaCreateContextExt(OSMESA_RGBA, 24, 8, 0, NULL); + if (currContext == NULL) + { + puts("OSMesa: OSMesaCreateContextExt() failed!"); + return false; + } + } + + currCtxFormat = GL_UNSIGNED_BYTE; + currCtxWidth = GPU_FRAMEBUFFER_NATIVE_WIDTH; + currCtxHeight = GPU_FRAMEBUFFER_NATIVE_HEIGHT; + + currCtxBuffer = malloc_alignedPage(currCtxWidth * currCtxHeight * sizeof(uint32_t)); + if (currCtxBuffer == NULL) + { + OSMesaDestroyContext(currContext); + currCtxFormat = GL_UNSIGNED_BYTE; + currCtxWidth = 0; + currCtxHeight = 0; + + puts("OSMesa: Could not allocate enough memory for the context!"); + return false; + } + + puts("OSMesa: Context creation successful."); + return true; +} + +bool osmesa_initOpenGL_StandardAuto() +{ + bool isContextCreated = __osmesa_initOpenGL(OSMESA_CORE_PROFILE, 4, 1); + + if (!isContextCreated) + { + isContextCreated = osmesa_initOpenGL_3_2_CoreProfile(); + } + + if (!isContextCreated) + { + isContextCreated = osmesa_initOpenGL_LegacyAuto(); + } + + return isContextCreated; +} + +bool osmesa_initOpenGL_LegacyAuto() +{ + return __osmesa_initOpenGL(OSMESA_COMPAT_PROFILE, 1, 2); +} + +bool osmesa_initOpenGL_3_2_CoreProfile() +{ + return __osmesa_initOpenGL(OSMESA_CORE_PROFILE, 3, 2); +} + +void osmesa_deinitOpenGL() +{ + OSMesaMakeCurrent(NULL, NULL, GL_UNSIGNED_BYTE, 0, 0); + + if (currContext != NULL) + { + OSMesaDestroyContext(currContext); + currContext = NULL; + currCtxFormat = GL_UNSIGNED_BYTE; + } + + if (currCtxBuffer != NULL) + { + free_aligned(currCtxBuffer); + currCtxBuffer = NULL; + currCtxWidth = 0; + currCtxHeight = 0; + } + + if (pendingCtxBuffer != NULL) + { + free_aligned(pendingCtxBuffer); + pendingCtxBuffer = NULL; + pendingCtxWidth = 0; + pendingCtxHeight = 0; + } + + prevContext = NULL; + prevCtxFormat = GL_UNSIGNED_BYTE; + prevCtxWidth = 0; + prevCtxHeight = 0; + prevCtxBuffer = NULL; +} + +bool osmesa_beginOpenGL() +{ + GLboolean ret = GL_FALSE; + OSMesaContext oldContext = OSMesaGetCurrentContext(); + + if (oldContext != NULL) + { + prevContext = oldContext; + OSMesaGetColorBuffer(prevContext, &prevCtxWidth, &prevCtxHeight, &prevCtxFormat, &prevCtxBuffer); + } + else + { + prevContext = currContext; + prevCtxFormat = currCtxFormat; + prevCtxWidth = currCtxWidth; + prevCtxHeight = currCtxHeight; + prevCtxBuffer = currCtxBuffer; + } + + if (pendingCtxBuffer != NULL) + { + bool previousIsCurrent = (prevCtxBuffer == currCtxBuffer); + + ret = OSMesaMakeCurrent(currContext, pendingCtxBuffer, currCtxFormat, pendingCtxWidth, pendingCtxHeight);; + if (ret == GL_TRUE) + { + free_aligned(currCtxBuffer); + currCtxBuffer = pendingCtxBuffer; + + if (previousIsCurrent) + { + prevCtxBuffer = pendingCtxBuffer; + prevCtxWidth = pendingCtxWidth; + prevCtxHeight = pendingCtxHeight; + } + + pendingCtxBuffer = NULL; + pendingCtxWidth = 0; + pendingCtxHeight = 0; + } + } + else + { + ret = OSMesaMakeCurrent(currContext, currCtxBuffer, currCtxFormat, currCtxWidth, currCtxHeight); + } + + return (ret == GL_TRUE); +} + +void osmesa_endOpenGL() +{ + if (prevContext == NULL) + { + prevContext = currContext; + } + + if (prevCtxBuffer == NULL) + { + prevCtxBuffer = currCtxBuffer; + } + + if (prevCtxWidth == 0) + { + prevCtxWidth = currCtxWidth; + } + + if (prevCtxHeight == 0) + { + prevCtxHeight = currCtxHeight; + } + + if (prevCtxFormat == GL_UNSIGNED_BYTE) + { + prevCtxFormat = currCtxFormat; + } + + if ( (prevContext != currContext) || + (prevCtxBuffer != currCtxBuffer) || + (prevCtxFormat != currCtxFormat) || + (prevCtxWidth != currCtxWidth) || + (prevCtxHeight != currCtxHeight) ) + { + OSMesaMakeCurrent(prevContext, prevCtxBuffer, prevCtxFormat, prevCtxWidth, prevCtxHeight); + } +} + +bool osmesa_framebufferDidResizeCallback(bool isFBOSupported, size_t w, size_t h) +{ + bool result = false; + + if (isFBOSupported) + { + result = true; + return result; + } + + if ( (w == (size_t)currCtxWidth) && (h == (size_t)currCtxHeight) ) + { + result = true; + return result; + } + + if (pendingCtxBuffer != NULL) + { + free_aligned(pendingCtxBuffer); + } + + pendingCtxWidth = (GLint)w; + pendingCtxHeight = (GLint)h; + pendingCtxBuffer = malloc_alignedPage(w * h * sizeof(uint32_t)); + + result = true; + return result; +} diff --git a/desmume/src/frontend/posix/gtk2/osmesa_3Demu.h b/desmume/src/frontend/posix/shared/osmesa_3Demu.h similarity index 68% rename from desmume/src/frontend/posix/gtk2/osmesa_3Demu.h rename to desmume/src/frontend/posix/shared/osmesa_3Demu.h index af6a9f4db..df452160e 100644 --- a/desmume/src/frontend/posix/gtk2/osmesa_3Demu.h +++ b/desmume/src/frontend/posix/shared/osmesa_3Demu.h @@ -1,27 +1,32 @@ /* Copyright (C) 2009 Guillaume Duhamel - Copyright (C) 2009-2017 DeSmuME team - + Copyright (C) 2009-2024 DeSmuME team + This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. - + This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #ifndef OSMESA_3DEMU_H -#define OSMESA_3DEMU_H - -bool init_osmesa_3Demu(void); -void deinit_osmesa_3Demu(void); -bool is_osmesa_initialized(void); +#define OSMESA_3DEMU_H + +bool osmesa_initOpenGL_StandardAuto(); +bool osmesa_initOpenGL_LegacyAuto(); +bool osmesa_initOpenGL_3_2_CoreProfile(); + +void osmesa_deinitOpenGL(); +bool osmesa_beginOpenGL(); +void osmesa_endOpenGL(); +bool osmesa_framebufferDidResizeCallback(bool isFBOSupported, size_t w, size_t h); #endif // OSMESA_3DEMU_H diff --git a/desmume/src/frontend/posix/shared/sdl_3Demu.cpp b/desmume/src/frontend/posix/shared/sdl_3Demu.cpp new file mode 100644 index 000000000..98f5e9a1d --- /dev/null +++ b/desmume/src/frontend/posix/shared/sdl_3Demu.cpp @@ -0,0 +1,232 @@ +/* + Copyright (C) 2020 Emmanuel Gil Peyrot + Copyright (C) 2020-2024 DeSmuME team + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the this software. If not, see . + */ + +#include +#include + +#include "sdl_3Demu.h" + + +static SDL_Window *currWindow = NULL; +static SDL_GLContext currContext = NULL; + +static SDL_Window *prevWindow = NULL; +static SDL_GLContext prevContext = NULL; + +static SDL_Window *pendingWindow = NULL; + +static bool __sdl_initOpenGL(const int requestedProfile, const int requestedVersionMajor, const int requestedVersionMinor) +{ + bool result = false; + char ctxString[32] = {0}; + + if (requestedProfile == SDL_GL_CONTEXT_PROFILE_CORE) + { + snprintf(ctxString, sizeof(ctxString), "SDL (Core %i.%i)", requestedVersionMajor, requestedVersionMinor); + } + else if (requestedProfile == SDL_GL_CONTEXT_PROFILE_COMPATIBILITY) + { + snprintf(ctxString, sizeof(ctxString), "SDL (Compatibility %i.%i)", requestedVersionMajor, requestedVersionMinor); + } + else if (requestedProfile == SDL_GL_CONTEXT_PROFILE_ES) + { + snprintf(ctxString, sizeof(ctxString), "SDL (ES %i.%i)", requestedVersionMajor, requestedVersionMinor); + } + else + { + puts("SDL: Invalid profile submitted. No context will be created."); + return result; + } + + if (currContext != NULL) + { + result = true; + return result; + } + + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, ((requestedProfile == SDL_GL_CONTEXT_PROFILE_CORE) || (requestedProfile == SDL_GL_CONTEXT_PROFILE_ES)) ? 0 : 24); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, ((requestedProfile == SDL_GL_CONTEXT_PROFILE_CORE) || (requestedProfile == SDL_GL_CONTEXT_PROFILE_ES)) ? 0 : 8); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, requestedProfile); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, requestedVersionMajor); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, requestedVersionMinor); + + currWindow = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 256, 192, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN); + if (currWindow == NULL) + { + fprintf(stderr, "%s: Failed to create a window: %s\n", ctxString, SDL_GetError()); + return false; + } + + currContext = SDL_GL_CreateContext(currWindow); + if (currContext == NULL) + { + SDL_DestroyWindow(currWindow); + currWindow = NULL; + + fprintf(stderr, "%s: Failed to create an OpenGL context: %s\n", ctxString, SDL_GetError()); + return false; + } + + printf("%s: OpenGL context creation successful.\n", ctxString); + return true; +} + +bool sdl_initOpenGL_StandardAuto() +{ + bool isContextCreated = sdl_initOpenGL_3_2_CoreProfile(); + + if (!isContextCreated) + { + isContextCreated = sdl_initOpenGL_LegacyAuto(); + } + + return isContextCreated; +} + +bool sdl_initOpenGL_LegacyAuto() +{ + return __sdl_initOpenGL(SDL_GL_CONTEXT_PROFILE_COMPATIBILITY, 1, 2); +} + +bool sdl_initOpenGL_3_2_CoreProfile() +{ + return __sdl_initOpenGL(SDL_GL_CONTEXT_PROFILE_CORE, 3, 2); +} + +bool sdl_initOpenGL_ES_3_0() +{ + return __sdl_initOpenGL(SDL_GL_CONTEXT_PROFILE_ES, 3, 0); +} + +void sdl_deinitOpenGL() +{ + SDL_GL_MakeCurrent(NULL, NULL); + + if (currContext != NULL) + { + SDL_GL_DeleteContext(currContext); + currContext = NULL; + } + + if (currWindow != NULL) + { + SDL_DestroyWindow(currWindow); + currWindow = NULL; + } + + if (pendingWindow != NULL) + { + SDL_DestroyWindow(pendingWindow); + pendingWindow = NULL; + } + + prevWindow = NULL; + prevContext = NULL; +} + +bool sdl_beginOpenGL() +{ + int ret = 1; + + prevWindow = SDL_GL_GetCurrentWindow(); + prevContext = SDL_GL_GetCurrentContext(); + + if (pendingWindow != NULL) + { + bool previousIsCurrent = (prevWindow == currWindow); + + ret = SDL_GL_MakeCurrent(pendingWindow, currContext); + if (ret == 0) + { + SDL_DestroyWindow(currWindow); + currWindow = pendingWindow; + + if (previousIsCurrent) + { + prevWindow = currWindow; + } + + pendingWindow = NULL; + } + } + else + { + ret = SDL_GL_MakeCurrent(currWindow, currContext); + } + + return (ret == 0); +} + +void sdl_endOpenGL() +{ + if (prevWindow == NULL) + { + prevWindow = currWindow; + } + + if (prevContext == NULL) + { + prevContext = currContext; + } + + if ( (prevWindow != currWindow) || + (prevContext != currContext) ) + { + SDL_GL_MakeCurrent(prevWindow, prevContext); + } +} + +bool sdl_framebufferDidResizeCallback(bool isFBOSupported, size_t w, size_t h) +{ + bool result = false; + + if (isFBOSupported) + { + result = true; + return result; + } + + int currWidth; + int currHeight; + SDL_GetWindowSize(currWindow, &currWidth, &currHeight); + + if ( (w == (size_t)currWidth) && (h == (size_t)currHeight) ) + { + result = true; + return result; + } + + if (pendingWindow != NULL) + { + SDL_DestroyWindow(pendingWindow); + } + + pendingWindow = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, (int)w, (int)h, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN); + if (currWindow == NULL) + { + fprintf(stderr, "SDL: sdl_framebufferDidResizeCallback failed to create the resized window: %s\n", SDL_GetError()); + return result; + } + + result = true; + return result; +} diff --git a/desmume/src/frontend/posix/gtk2/sdl_3Demu.h b/desmume/src/frontend/posix/shared/sdl_3Demu.h similarity index 68% rename from desmume/src/frontend/posix/gtk2/sdl_3Demu.h rename to desmume/src/frontend/posix/shared/sdl_3Demu.h index 2088263da..2e9b5fe2d 100644 --- a/desmume/src/frontend/posix/gtk2/sdl_3Demu.h +++ b/desmume/src/frontend/posix/shared/sdl_3Demu.h @@ -1,16 +1,17 @@ /* Copyright (C) 2020 Emmanuel Gil Peyrot - + Copyright (C) 2020-2024 DeSmuME team + This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. - + This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with the this software. If not, see . */ @@ -18,9 +19,15 @@ #ifndef SDL_3DEMU_H #define SDL_3DEMU_H -bool init_sdl_3Demu(void); -bool deinit_sdl_3Demu(void); -bool is_sdl_initialized(void); +bool sdl_initOpenGL_StandardAuto(); +bool sdl_initOpenGL_LegacyAuto(); +bool sdl_initOpenGL_3_2_CoreProfile(); +bool sdl_initOpenGL_ES_3_0(); + +void sdl_deinitOpenGL(); +bool sdl_beginOpenGL(); +void sdl_endOpenGL(); +bool sdl_framebufferDidResizeCallback(bool isFBOSupported, size_t w, size_t h); #endif // SDL_3DEMU_H