OpenGL Renderer: Finalize all renderer-client integration to "just work".

- These changes now presume that standard OpenGL and OpenGL ES are mutually exclusive. We will NOT support running a standard OpenGL context and an OpenGL ES context in the same process.
- Clients must explicitly request supporting the OpenGL 3D renderer in their build configuration. Build configurations must define ENABLE_OPENGL_STANDARD (replacing the HAVE_OPENGL macro) or ENABLE_OPENGL_ES. If neither macro is defined, then the OpenGL 3D renderer will be assumed unavailable.
- Meson and Autotools now use better header/library checks for OpenGL functionality with their associated context type.
- Add a new Code::Blocks project file that can make builds for CLI, GTK, and GTK2.
- GTK and GTK2 ports now have the option to run a legacy OpenGL context, a 3.2 Core Profile context, or simply choosing the best context automatically like before.
- GTK and GTK2 ports have GLX and EGL as new context types. OSMesa and SDL have been updated to the latest design pattern.
- GTK and GTK2 ports can now be configured (via Meson or Autotools) to use a GLX, OSMesa, EGL, or SDL context.
- OSMesa contexts are now marked as deprecated. I don't know of anyone who still uses them, and I've never been able to get it to work correctly for years. Now that we have GLX contexts for compatibility purposes, OSMesa contexts are now completely redundant.
- Fix a bug with the GTK port where ancient GPUs without FBO support can still run framebuffers at custom sizes.
- For POSIX ports, move all "avout" and context creation files to the "shared" directory for better file organization.
This commit is contained in:
rogerman 2024-08-01 17:08:01 -07:00
parent 0a78fa2a2b
commit ca566eb11b
44 changed files with 3572 additions and 1081 deletions

View File

@ -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

View File

@ -27,29 +27,15 @@
#include "render3D.h"
#include "types.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.
// OPENGL PLATFORM-SPECIFIC INCLUDES
#if defined(__ANGLE__) || defined(__ANDROID__)
#define OPENGL_VARIANT_ES
#define _NO_SDL_TYPES
#include <GLES3/gl3.h>
#define __gles2_gl2_h_ // Guard against including the gl2.h file.
#include <GLES2/gl2ext.h> // "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(__EMSCRIPTEN__)
#define OPENGL_VARIANT_ES
#include <SDL_opengl.h>
#include <emscripten/emscripten.h>
// Ignore dynamic linking
#define OGLEXT(procPtr, func)
#define INITOGLEXT(procPtr, func)
#define EXTERNOGLEXT(procPtr, func)
#elif defined(_WIN32)
#define OPENGL_VARIANT_STANDARD
#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 <windows.h>
#include <GL/gl.h>
@ -63,15 +49,10 @@
#define INITOGLEXT(procPtr, func) func = (procPtr)wglGetProcAddress(#func);
#define EXTERNOGLEXT(procPtr, func) extern procPtr func;
#elif defined(__APPLE__)
#include <TargetConditionals.h>
#if TARGET_OS_IPHONE
#define OPENGL_VARIANT_ES
#if defined(ENABLE_OPENGL_ES)
#include <OpenGLES/ES3/gl.h>
#include <OpenGLES/ES3/glext.h>
#else
#define OPENGL_VARIANT_STANDARD
#elif defined(ENABLE_OPENGL_STANDARD)
#ifdef OGLRENDER_3_2_H
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>
@ -93,7 +74,16 @@
#define INITOGLEXT(procPtr, func)
#define EXTERNOGLEXT(procPtr, func)
#else
#define OPENGL_VARIANT_STANDARD
#if defined(ENABLE_OPENGL_ES)
#include <GLES3/gl3.h>
#define __gles2_gl2_h_ // Guard against including the gl2.h file.
#include <GLES2/gl2ext.h> // "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 <GL/gl.h>
#include <GL/glext.h>
#include <GL/glx.h>
@ -101,7 +91,7 @@
#ifdef OGLRENDER_3_2_H
#include "utils/glcorearb.h"
#else
/* This is a workaround needed to compile against nvidia GL headers */
// This is a workaround needed to compile against nvidia GL headers
#ifndef GL_ALPHA_BLEND_EQUATION_ATI
#undef GL_VERSION_1_3
#endif
@ -111,18 +101,19 @@
#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

View File

@ -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 = "<group>"; };
ABD42046172319D1006A9B46 /* FileMigrationDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FileMigrationDelegate.mm; sourceTree = "<group>"; };
ABDD89EF2C30BE97003482B7 /* OGLRender_ES3.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OGLRender_ES3.h; sourceTree = "<group>"; };
ABDD89F02C30BE97003482B7 /* OGLRender_ES3.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = OGLRender_ES3.cpp; sourceTree = "<group>"; };
ABDDF7C41898F024007583C1 /* Icon_DisplayToggle_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_DisplayToggle_420x420.png; path = images/Icon_DisplayToggle_420x420.png; sourceTree = "<group>"; };
ABDDF7C71898F032007583C1 /* Icon_FrameAdvance_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_FrameAdvance_420x420.png; path = images/Icon_FrameAdvance_420x420.png; sourceTree = "<group>"; };
ABDDF7C81898F032007583C1 /* Icon_FrameJump_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_FrameJump_420x420.png; path = images/Icon_FrameJump_420x420.png; sourceTree = "<group>"; };
@ -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 */,

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -70,32 +70,139 @@ else
AC_MSG_ERROR([sdl is required to build desmume])
fi
dnl - Check for the OpenGL includes
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/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.])
[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
AM_CONDITIONAL([HAVE_GL], [test "${have_gl_h}" = "yes"])
fi
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_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,[
useosmesa=yes
AC_DEFINE(HAVE_LIBOSMESA)
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
AM_CONDITIONAL([HAVE_LIBOSMESA], [test "${useosmesa}" = "yes"])
fi
AM_CONDITIONAL([ENABLE_EGL], [test "${have_egl}" = "yes"])
dnl - make the usage of libagg for HUD rendering configurable
AC_ARG_ENABLE([hud],

View File

@ -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
desmume_LDADD += $(OSMESA_LIBS)
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 = \

View File

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.40.0 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkDialog" id="dialog">
@ -49,40 +50,49 @@
</packing>
</child>
<child>
<!-- n-columns=3 n-rows=6 -->
<object class="GtkGrid" id="graphics_grid">
<property name="can-focus">False</property>
<child>
<object class="GtkLabel">
<property name="can-focus">False</property>
<property name="label" translatable="yes">3D Core:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="core_combo">
<property name="can-focus">False</property>
<items>
<item translatable="yes">Null</item>
<item translatable="yes">SoftRasterizer</item>
<item translatable="yes">OpenGL</item>
<item translatable="yes">OpenGL (Auto)</item>
<item translatable="yes">OpenGL (Legacy)</item>
<item translatable="yes">OpenGL 3.2</item>
<item translatable="yes">OpenGL ES 3.0</item>
</items>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="can-focus">False</property>
<property name="label" translatable="yes">3D Texture Upscaling:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="scale">
<property name="can-focus">False</property>
<items>
<item translatable="yes">×1</item>
<item translatable="yes">×2</item>
@ -90,70 +100,79 @@
</items>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="can-focus">False</property>
<property name="label" translatable="yes">GPU scale factor:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="gpuscale">
<property name="numeric">true</property>
<property name="digits">0</property>
<property name="can-focus">False</property>
<property name="numeric">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="posterize">
<property name="label" translatable="yes">3D Texture Deposterization</property>
<property name="can-focus">False</property>
<property name="receives-default">False</property>
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="smoothing">
<property name="label" translatable="yes">3D Texture Smoothing</property>
<property name="can-focus">False</property>
<property name="receives-default">False</property>
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">4</property>
<property name="left-attach">0</property>
<property name="top-attach">4</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="hc_interpolate">
<property name="label" translatable="yes">High Resolution Color Interpolation (SoftRasterizer)</property>
<property name="can-focus">False</property>
<property name="receives-default">False</property>
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">4</property>
<property name="left-attach">1</property>
<property name="top-attach">4</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="can-focus">False</property>
<property name="label" translatable="yes">Multisample Antialiasing (OpenGL):</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">5</property>
<property name="left-attach">0</property>
<property name="top-attach">5</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="multisample">
<property name="can-focus">False</property>
<items>
<item translatable="yes">None</item>
<item translatable="yes">2</item>
@ -164,11 +183,37 @@
</items>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">5</property>
<property name="left-attach">1</property>
<property name="top-attach">5</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>

View File

@ -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 <GL/gl.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(HAVE_LIBOSMESA)
#include "osmesa_3Demu.h"
#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 "sdl_3Demu.h"
#include "../shared/sdl_3Demu.h"
#endif
#endif
#include "config.h"
@ -346,9 +351,14 @@ NULL
GPU3DInterface *core3DList[] = {
&gpu3DNull,
&gpu3DRasterize,
#ifdef HAVE_OPENGL
#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};
@ -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");
@ -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();
}
#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
if (!is_sdl_initialized())
{
init_sdl_3Demu();
}
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:
{
if (sel3DCore > 0)
{
sel3DCore = RENDERID_SOFTRASTERIZER;
}
else
{
sel3DCore = RENDERID_NULL;
}
break;
}
}
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;
@ -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
#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();
}
#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
if (!is_sdl_initialized())
{
init_sdl_3Demu();
}
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:
{
if (core > 0)
{
core = RENDERID_SOFTRASTERIZER;
}
else
{
core = RENDERID_NULL;
}
break;
}
}
if (!GPU->Change3DRendererByID(core)) {
@ -3923,11 +4069,17 @@ static void Teardown() {
desmume_free();
#if defined(HAVE_LIBOSMESA)
deinit_osmesa_3Demu();
#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
deinit_sdl_3Demu();
sdl_deinitOpenGL();
#endif
#endif // ENABLE_OPENGL_STANDARD || ENABLE_OPENGL_ES
/* Unload joystick */
uninit_joy();

View File

@ -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',

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_LIBOSMESA
#include <stdlib.h>
#include <GL/osmesa.h>
#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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <SDL.h>
#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);
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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

View File

@ -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
desmume_LDADD += $(OSMESA_LIBS)
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 = \

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <cstring>
#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;
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <unistd.h>
#include <cerrno>
#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();
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <cstring>
#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;
}

View File

@ -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 <GL/gl.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(HAVE_LIBOSMESA)
#include "osmesa_3Demu.h"
#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 "sdl_3Demu.h"
#include "../shared/sdl_3Demu.h"
#endif
#endif
#include "config.h"
@ -634,9 +639,14 @@ NULL
GPU3DInterface *core3DList[] = {
&gpu3DNull,
&gpu3DRasterize,
#ifdef HAVE_OPENGL
#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};
@ -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");
@ -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<GtkAttachOptions>(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();
}
#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
if (!is_sdl_initialized())
{
init_sdl_3Demu();
}
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:
{
if (sel3DCore > 0)
{
sel3DCore = RENDERID_SOFTRASTERIZER;
}
else
{
sel3DCore = RENDERID_NULL;
}
break;
}
}
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;
@ -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
#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();
}
#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
if (!is_sdl_initialized())
{
init_sdl_3Demu();
}
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:
{
if (core > 0)
{
core = RENDERID_SOFTRASTERIZER;
}
else
{
core = RENDERID_NULL;
}
break;
}
}
if (!GPU->Change3DRendererByID(core)) {
@ -3715,11 +3855,17 @@ common_gtk_main( class configured_features *my_config)
desmume_free();
#if defined(HAVE_LIBOSMESA)
deinit_osmesa_3Demu();
#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
deinit_sdl_3Demu();
sdl_deinitOpenGL();
#endif
#endif // ENABLE_OPENGL_STANDARD || ENABLE_OPENGL_ES
/* Unload joystick */
uninit_joy();

View File

@ -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',

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_LIBOSMESA
#include <stdlib.h>
#include <GL/osmesa.h>
#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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <SDL.h>
#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);
}

View File

@ -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 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()

View File

@ -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,

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <string.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#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;
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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__

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <GL/glx.h>
#include <GL/glxext.h>
#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;
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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__

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <GL/osmesa.h>
#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;
}

View File

@ -1,6 +1,6 @@
/*
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
@ -19,9 +19,14 @@
#ifndef OSMESA_3DEMU_H
#define OSMESA_3DEMU_H
bool init_osmesa_3Demu(void);
void deinit_osmesa_3Demu(void);
bool is_osmesa_initialized(void);
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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <SDL.h>
#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;
}

View File

@ -1,5 +1,6 @@
/*
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
@ -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