diff --git a/.gitignore b/.gitignore
index c3d7b1e9a..099b15322 100644
--- a/.gitignore
+++ b/.gitignore
@@ -118,6 +118,7 @@ test/testgamecontroller
test/testgeometry
test/testgesture
test/testgl2
+test/testgles
test/testgles2
test/testhaptic
test/testhittesting
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8b72faf17..1386072d6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1290,6 +1290,8 @@ if(ANDROID)
if(SDL_OPENGLES)
set(SDL_VIDEO_OPENGL_EGL 1)
set(HAVE_OPENGLES TRUE)
+ set(SDL_VIDEO_OPENGL_ES 1)
+ set(SDL_VIDEO_RENDER_OGL_ES 1)
set(SDL_VIDEO_OPENGL_ES2 1)
set(SDL_VIDEO_RENDER_OGL_ES2 1)
@@ -2091,7 +2093,11 @@ elseif(APPLE)
endif()
if(SDL_OPENGLES)
- if(NOT (IOS OR TVOS))
+ if(IOS OR TVOS)
+ set(SDL_FRAMEWORK_OPENGLES 1)
+ set(SDL_VIDEO_OPENGL_ES 1)
+ set(SDL_VIDEO_RENDER_OGL_ES 1)
+ else()
set(SDL_VIDEO_OPENGL_EGL 1)
endif()
set(SDL_VIDEO_OPENGL_ES2 1)
@@ -2180,6 +2186,9 @@ elseif(APPLE)
list(APPEND EXTRA_LDFLAGS "-Wl,-weak_framework,Metal")
endif()
endif()
+ if(SDL_FRAMEWORK_OPENGLES)
+ list(APPEND EXTRA_LDFLAGS "-Wl,-framework,OpenGLES")
+ endif()
if(SDL_FRAMEWORK_QUARTZCORE)
if(IOS OR TVOS)
list(APPEND EXTRA_LDFLAGS "-Wl,-framework,QuartzCore")
@@ -2402,6 +2411,8 @@ elseif(VITA)
check_include_file(gl4esinit.h HAVE_GL4ES_H)
set(SDL_VIDEO_OPENGL_EGL 1)
set(HAVE_OPENGLES TRUE)
+ set(SDL_VIDEO_OPENGL_ES 1)
+ set(SDL_VIDEO_RENDER_OGL_ES 1)
set(SDL_VIDEO_OPENGL_ES2 1)
set(SDL_VIDEO_RENDER_OGL_ES2 1)
diff --git a/Makefile.in b/Makefile.in
index 5ff6e8beb..96dfed9ac 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -100,6 +100,7 @@ HDRS = \
SDL_name.h \
SDL_opengl.h \
SDL_opengl_glext.h \
+ SDL_opengles.h \
SDL_opengles2_gl2ext.h \
SDL_opengles2_gl2.h \
SDL_opengles2_gl2platform.h \
diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj
index 5e5179772..cc02748da 100644
--- a/VisualC-GDK/SDL/SDL.vcxproj
+++ b/VisualC-GDK/SDL/SDL.vcxproj
@@ -329,6 +329,7 @@
+
diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters
index e45001412..c8a757b1e 100644
--- a/VisualC-GDK/SDL/SDL.vcxproj.filters
+++ b/VisualC-GDK/SDL/SDL.vcxproj.filters
@@ -282,6 +282,9 @@
API Headers
+
+ API Headers
+
API Headers
diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj
index 821777883..d1adc6b98 100644
--- a/VisualC/SDL/SDL.vcxproj
+++ b/VisualC/SDL/SDL.vcxproj
@@ -253,6 +253,7 @@
+
diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters
index 9385a7fbb..d5cb6a87b 100644
--- a/VisualC/SDL/SDL.vcxproj.filters
+++ b/VisualC/SDL/SDL.vcxproj.filters
@@ -282,6 +282,9 @@
API Headers
+
+ API Headers
+
API Headers
diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake
index c6a679f7e..01fbbc396 100644
--- a/cmake/sdlchecks.cmake
+++ b/cmake/sdlchecks.cmake
@@ -700,6 +700,15 @@ endmacro()
# - nada
macro(CheckOpenGLES)
if(SDL_OPENGLES)
+ check_c_source_compiles("
+ #include
+ #include
+ int main (int argc, char** argv) { return 0; }" HAVE_OPENGLES_V1)
+ if(HAVE_OPENGLES_V1)
+ set(HAVE_OPENGLES TRUE)
+ set(SDL_VIDEO_OPENGL_ES 1)
+ set(SDL_VIDEO_RENDER_OGL_ES 1)
+ endif()
check_c_source_compiles("
#include
#include
diff --git a/configure b/configure
index 0bf207ced..1e59e861e 100755
--- a/configure
+++ b/configure
@@ -911,6 +911,7 @@ enable_video_dummy
enable_video_offscreen
enable_video_opengl
enable_video_opengles
+enable_video_opengles1
enable_video_opengles2
enable_video_vulkan
enable_libudev
@@ -1705,6 +1706,8 @@ Optional Features:
use offscreen video driver [default=yes]
--enable-video-opengl include OpenGL support [default=yes]
--enable-video-opengles include OpenGL ES support [default=yes]
+ --enable-video-opengles1
+ include OpenGL ES 1.1 support [default=yes]
--enable-video-opengles2
include OpenGL ES 2.0 support [default=yes]
--enable-video-vulkan include Vulkan support [default=yes]
@@ -24665,6 +24668,14 @@ else $as_nop
enable_video_opengles=yes
fi
+# Check whether --enable-video-opengles1 was given.
+if test ${enable_video_opengles1+y}
+then :
+ enableval=$enable_video_opengles1;
+else $as_nop
+ enable_video_opengles1=yes
+fi
+
# Check whether --enable-video-opengles2 was given.
if test ${enable_video_opengles2+y}
then :
@@ -24755,6 +24766,42 @@ printf "%s\n" "#define SDL_VIDEO_RENDER_OGL 1" >>confdefs.h
CheckOpenGLES()
{
if test x$enable_video = xyes -a x$enable_video_opengles = xyes; then
+ if test x$enable_video_opengles1 = xyes; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OpenGL ES v1 headers" >&5
+printf %s "checking for OpenGL ES v1 headers... " >&6; }
+ video_opengles_v1=no
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include
+ #include
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ video_opengles_v1=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $video_opengles_v1" >&5
+printf "%s\n" "$video_opengles_v1" >&6; }
+ if test x$video_opengles_v1 = xyes; then
+
+printf "%s\n" "#define SDL_VIDEO_OPENGL_ES 1" >>confdefs.h
+
+
+printf "%s\n" "#define SDL_VIDEO_RENDER_OGL_ES 1" >>confdefs.h
+
+ SUMMARY_video="${SUMMARY_video} opengl_es1"
+ fi
+ fi
+
if test x$enable_video_opengles2 = xyes; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OpenGL ES v2 headers" >&5
printf %s "checking for OpenGL ES v2 headers... " >&6; }
@@ -27930,6 +27977,12 @@ printf "%s\n" "#define SDL_VIDEO_DRIVER_UIKIT 1" >>confdefs.h
printf "%s\n" "#define SDL_VIDEO_OPENGL_ES2 1" >>confdefs.h
+printf "%s\n" "#define SDL_VIDEO_OPENGL_ES 1" >>confdefs.h
+
+
+printf "%s\n" "#define SDL_VIDEO_RENDER_OGL_ES 1" >>confdefs.h
+
+
printf "%s\n" "#define SDL_VIDEO_RENDER_OGL_ES2 1" >>confdefs.h
SOURCES="$SOURCES $srcdir/src/video/uikit/*.m"
@@ -27947,6 +28000,7 @@ printf "%s\n" "#define SDL_VIDEO_RENDER_OGL_ES2 1" >>confdefs.h
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,CoreMotion"
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Foundation"
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,GameController"
+ EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,OpenGLES"
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,QuartzCore"
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,UIKit"
diff --git a/configure.ac b/configure.ac
index 208ec49c2..f8e71411d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2211,6 +2211,9 @@ dnl Check to see if OpenGL ES support is desired
AC_ARG_ENABLE(video-opengles,
[AS_HELP_STRING([--enable-video-opengles], [include OpenGL ES support [default=yes]])],
, enable_video_opengles=yes)
+AC_ARG_ENABLE(video-opengles1,
+[AS_HELP_STRING([--enable-video-opengles1], [include OpenGL ES 1.1 support [default=yes]])],
+ , enable_video_opengles1=yes)
AC_ARG_ENABLE(video-opengles2,
[AS_HELP_STRING([--enable-video-opengles2], [include OpenGL ES 2.0 support [default=yes]])],
, enable_video_opengles2=yes)
@@ -2259,6 +2262,21 @@ dnl Find OpenGL ES
CheckOpenGLES()
{
if test x$enable_video = xyes -a x$enable_video_opengles = xyes; then
+ if test x$enable_video_opengles1 = xyes; then
+ AC_MSG_CHECKING(for OpenGL ES v1 headers)
+ video_opengles_v1=no
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #include
+ #include
+ ]],[])], [video_opengles_v1=yes],[])
+ AC_MSG_RESULT($video_opengles_v1)
+ if test x$video_opengles_v1 = xyes; then
+ AC_DEFINE(SDL_VIDEO_OPENGL_ES, 1, [ ])
+ AC_DEFINE(SDL_VIDEO_RENDER_OGL_ES, 1, [ ])
+ SUMMARY_video="${SUMMARY_video} opengl_es1"
+ fi
+ fi
+
if test x$enable_video_opengles2 = xyes; then
AC_MSG_CHECKING(for OpenGL ES v2 headers)
video_opengles_v2=no
@@ -3966,6 +3984,8 @@ dnl BeOS support removed after SDL 2.0.1. Haiku still works. --ryan.
# The iOS platform requires special setup.
AC_DEFINE(SDL_VIDEO_DRIVER_UIKIT, 1, [ ])
AC_DEFINE(SDL_VIDEO_OPENGL_ES2, 1, [ ])
+ AC_DEFINE(SDL_VIDEO_OPENGL_ES, 1, [ ])
+ AC_DEFINE(SDL_VIDEO_RENDER_OGL_ES, 1, [ ])
AC_DEFINE(SDL_VIDEO_RENDER_OGL_ES2, 1, [ ])
SOURCES="$SOURCES $srcdir/src/video/uikit/*.m"
SUMMARY_video="${SUMMARY_video} uikit"
@@ -3982,6 +4002,7 @@ dnl BeOS support removed after SDL 2.0.1. Haiku still works. --ryan.
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,CoreMotion"
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Foundation"
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,GameController"
+ EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,OpenGLES"
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,QuartzCore"
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,UIKit"
diff --git a/docs/doxyfile b/docs/doxyfile
index fa7d2d483..a9d837c32 100644
--- a/docs/doxyfile
+++ b/docs/doxyfile
@@ -637,6 +637,7 @@ EXCLUDE = ../include/SDL_opengles2_gl2ext.h \
../include/SDL_opengl_glext.h \
../include/SDL_opengles2_gl2.h \
../include/SDL_opengles2.h \
+ ../include/SDL_opengles.h \
../include/SDL_opengl.h \
../include/SDL_egl.h \
./release_checklist.md \
diff --git a/include/SDL_config.h.cmake b/include/SDL_config.h.cmake
index fef07118a..c52ca5437 100644
--- a/include/SDL_config.h.cmake
+++ b/include/SDL_config.h.cmake
@@ -434,6 +434,7 @@
#cmakedefine SDL_VIDEO_RENDER_D3D11 @SDL_VIDEO_RENDER_D3D11@
#cmakedefine SDL_VIDEO_RENDER_D3D12 @SDL_VIDEO_RENDER_D3D12@
#cmakedefine SDL_VIDEO_RENDER_OGL @SDL_VIDEO_RENDER_OGL@
+#cmakedefine SDL_VIDEO_RENDER_OGL_ES @SDL_VIDEO_RENDER_OGL_ES@
#cmakedefine SDL_VIDEO_RENDER_OGL_ES2 @SDL_VIDEO_RENDER_OGL_ES2@
#cmakedefine SDL_VIDEO_RENDER_METAL @SDL_VIDEO_RENDER_METAL@
#cmakedefine SDL_VIDEO_RENDER_VITA_GXM @SDL_VIDEO_RENDER_VITA_GXM@
@@ -442,6 +443,7 @@
/* Enable OpenGL support */
#cmakedefine SDL_VIDEO_OPENGL @SDL_VIDEO_OPENGL@
+#cmakedefine SDL_VIDEO_OPENGL_ES @SDL_VIDEO_OPENGL_ES@
#cmakedefine SDL_VIDEO_OPENGL_ES2 @SDL_VIDEO_OPENGL_ES2@
#cmakedefine SDL_VIDEO_OPENGL_BGL @SDL_VIDEO_OPENGL_BGL@
#cmakedefine SDL_VIDEO_OPENGL_CGL @SDL_VIDEO_OPENGL_CGL@
diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in
index 0bf7b6fc6..fe2a25594 100644
--- a/include/SDL_config.h.in
+++ b/include/SDL_config.h.in
@@ -395,11 +395,13 @@
#undef SDL_VIDEO_RENDER_D3D11
#undef SDL_VIDEO_RENDER_D3D12
#undef SDL_VIDEO_RENDER_OGL
+#undef SDL_VIDEO_RENDER_OGL_ES
#undef SDL_VIDEO_RENDER_OGL_ES2
#undef SDL_VIDEO_RENDER_METAL
/* Enable OpenGL support */
#undef SDL_VIDEO_OPENGL
+#undef SDL_VIDEO_OPENGL_ES
#undef SDL_VIDEO_OPENGL_ES2
#undef SDL_VIDEO_OPENGL_BGL
#undef SDL_VIDEO_OPENGL_CGL
diff --git a/include/SDL_config_android.h b/include/SDL_config_android.h
index 6707c26d1..64918ae0b 100644
--- a/include/SDL_config_android.h
+++ b/include/SDL_config_android.h
@@ -171,8 +171,10 @@
#define SDL_VIDEO_DRIVER_ANDROID 1
/* Enable OpenGL ES */
+#define SDL_VIDEO_OPENGL_ES 1
#define SDL_VIDEO_OPENGL_ES2 1
#define SDL_VIDEO_OPENGL_EGL 1
+#define SDL_VIDEO_RENDER_OGL_ES 1
#define SDL_VIDEO_RENDER_OGL_ES2 1
/* Enable Vulkan support */
diff --git a/include/SDL_config_emscripten.h b/include/SDL_config_emscripten.h
index ea41fc960..989e1243a 100644
--- a/include/SDL_config_emscripten.h
+++ b/include/SDL_config_emscripten.h
@@ -199,6 +199,7 @@
/* Enable OpenGL support */
/* #undef SDL_VIDEO_OPENGL */
+/* #undef SDL_VIDEO_OPENGL_ES */
#define SDL_VIDEO_OPENGL_ES2 1
/* #undef SDL_VIDEO_OPENGL_BGL */
/* #undef SDL_VIDEO_OPENGL_CGL */
diff --git a/include/SDL_config_iphoneos.h b/include/SDL_config_iphoneos.h
index 57099b814..6db16eb4c 100644
--- a/include/SDL_config_iphoneos.h
+++ b/include/SDL_config_iphoneos.h
@@ -176,6 +176,8 @@
/* Enable OpenGL ES */
#if !TARGET_OS_MACCATALYST
#define SDL_VIDEO_OPENGL_ES2 1
+#define SDL_VIDEO_OPENGL_ES 1
+#define SDL_VIDEO_RENDER_OGL_ES 1
#define SDL_VIDEO_RENDER_OGL_ES2 1
#endif
diff --git a/include/SDL_opengles.h b/include/SDL_opengles.h
new file mode 100644
index 000000000..8511b9607
--- /dev/null
+++ b/include/SDL_opengles.h
@@ -0,0 +1,39 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2022 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_opengles.h
+ *
+ * This is a simple file to encapsulate the OpenGL ES 1.X API headers.
+ */
+#include "SDL_config.h"
+
+#ifdef __IPHONEOS__
+#include
+#include
+#else
+#include
+#include
+#endif
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c
index 39fa911ea..d103e958e 100644
--- a/src/render/SDL_render.c
+++ b/src/render/SDL_render.c
@@ -109,6 +109,9 @@ static const SDL_RenderDriver *render_drivers[] = {
#if SDL_VIDEO_RENDER_OGL_ES2
&GLES2_RenderDriver,
#endif
+#if SDL_VIDEO_RENDER_OGL_ES
+ &GLES_RenderDriver,
+#endif
#if SDL_VIDEO_RENDER_PS2 && !SDL_RENDER_DISABLED
&PS2_RenderDriver,
#endif
diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h
index 49c682aec..d9b6651c4 100644
--- a/src/render/SDL_sysrender.h
+++ b/src/render/SDL_sysrender.h
@@ -299,6 +299,7 @@ extern SDL_RenderDriver D3D11_RenderDriver;
extern SDL_RenderDriver D3D12_RenderDriver;
extern SDL_RenderDriver GL_RenderDriver;
extern SDL_RenderDriver GLES2_RenderDriver;
+extern SDL_RenderDriver GLES_RenderDriver;
extern SDL_RenderDriver METAL_RenderDriver;
extern SDL_RenderDriver PS2_RenderDriver;
extern SDL_RenderDriver PSP_RenderDriver;
diff --git a/src/render/opengles/SDL_glesfuncs.h b/src/render/opengles/SDL_glesfuncs.h
new file mode 100644
index 000000000..40a656455
--- /dev/null
+++ b/src/render/opengles/SDL_glesfuncs.h
@@ -0,0 +1,62 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2022 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+SDL_PROC(void, glBindTexture, (GLenum, GLuint))
+SDL_PROC(void, glBlendFunc, (GLenum, GLenum))
+SDL_PROC_OES(void, glBlendEquationOES, (GLenum))
+SDL_PROC_OES(void, glBlendEquationSeparateOES, (GLenum, GLenum))
+SDL_PROC_OES(void, glBlendFuncSeparateOES, (GLenum, GLenum, GLenum, GLenum))
+SDL_PROC(void, glClear, (GLbitfield))
+SDL_PROC(void, glClearColor, (GLclampf, GLclampf, GLclampf, GLclampf))
+SDL_PROC(void, glColor4f, (GLfloat, GLfloat, GLfloat, GLfloat))
+SDL_PROC(void, glColorPointer, (GLint, GLenum, GLsizei, const GLvoid *))
+SDL_PROC(void, glDeleteTextures, (GLsizei, const GLuint *))
+SDL_PROC(void, glDisable, (GLenum))
+SDL_PROC(void, glDisableClientState, (GLenum array))
+SDL_PROC(void, glDrawArrays, (GLenum, GLint, GLsizei))
+SDL_PROC_OES(void, glDrawTexfOES, (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat))
+SDL_PROC(void, glEnable, (GLenum))
+SDL_PROC(void, glEnableClientState, (GLenum))
+SDL_PROC(void, glFinish, (void))
+SDL_PROC_OES(void, glGenFramebuffersOES, (GLsizei, GLuint *))
+SDL_PROC(void, glGenTextures, (GLsizei, GLuint *))
+SDL_PROC(GLenum, glGetError, (void))
+SDL_PROC(void, glGetIntegerv, (GLenum, GLint *))
+SDL_PROC(void, glLoadIdentity, (void))
+SDL_PROC(void, glMatrixMode, (GLenum))
+SDL_PROC(void, glOrthof, (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat))
+SDL_PROC(void, glPixelStorei, (GLenum, GLint))
+SDL_PROC(void, glReadPixels, (GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid*))
+SDL_PROC(void, glScissor, (GLint, GLint, GLsizei, GLsizei))
+SDL_PROC(void, glTexCoordPointer, (GLint, GLenum, GLsizei, const GLvoid *))
+SDL_PROC(void, glTexEnvf, (GLenum, GLenum, GLfloat))
+SDL_PROC(void, glTexImage2D, (GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *))
+SDL_PROC(void, glTexParameteri, (GLenum, GLenum, GLint))
+SDL_PROC(void, glTexParameteriv, (GLenum, GLenum, const GLint *))
+SDL_PROC(void, glTexSubImage2D, (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *))
+SDL_PROC(void, glVertexPointer, (GLint, GLenum, GLsizei, const GLvoid *))
+SDL_PROC(void, glViewport, (GLint, GLint, GLsizei, GLsizei))
+SDL_PROC_OES(void, glBindFramebufferOES, (GLenum, GLuint))
+SDL_PROC_OES(void, glFramebufferTexture2DOES, (GLenum, GLenum, GLenum, GLuint, GLint))
+SDL_PROC_OES(GLenum, glCheckFramebufferStatusOES, (GLenum))
+SDL_PROC_OES(void, glDeleteFramebuffersOES, (GLsizei, const GLuint*))
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/render/opengles/SDL_render_gles.c b/src/render/opengles/SDL_render_gles.c
new file mode 100644
index 000000000..8e918c665
--- /dev/null
+++ b/src/render/opengles/SDL_render_gles.c
@@ -0,0 +1,1218 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2022 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_RENDER_OGL_ES && !SDL_RENDER_DISABLED
+
+#include "SDL_hints.h"
+#include "../../video/SDL_sysvideo.h" /* For SDL_GL_SwapWindowWithResult */
+#include "SDL_opengles.h"
+#include "../SDL_sysrender.h"
+#include "../../SDL_utils_c.h"
+
+/* To prevent unnecessary window recreation,
+ * these should match the defaults selected in SDL_GL_ResetAttributes
+ */
+
+#define RENDERER_CONTEXT_MAJOR 1
+#define RENDERER_CONTEXT_MINOR 1
+
+/* OpenGL ES 1.1 renderer implementation, based on the OpenGL renderer */
+
+/* Used to re-create the window with OpenGL ES capability */
+extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags);
+
+static const float inv255f = 1.0f / 255.0f;
+
+typedef struct GLES_FBOList GLES_FBOList;
+
+struct GLES_FBOList
+{
+ Uint32 w, h;
+ GLuint FBO;
+ GLES_FBOList *next;
+};
+
+typedef struct
+{
+ SDL_Rect viewport;
+ SDL_bool viewport_dirty;
+ SDL_Texture *texture;
+ SDL_Texture *target;
+ int drawablew;
+ int drawableh;
+ SDL_BlendMode blend;
+ SDL_bool cliprect_enabled_dirty;
+ SDL_bool cliprect_enabled;
+ SDL_bool cliprect_dirty;
+ SDL_Rect cliprect;
+ SDL_bool texturing;
+ Uint32 color;
+ Uint32 clear_color;
+} GLES_DrawStateCache;
+
+typedef struct
+{
+ SDL_GLContext context;
+
+#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
+#define SDL_PROC_OES SDL_PROC
+#include "SDL_glesfuncs.h"
+#undef SDL_PROC
+#undef SDL_PROC_OES
+ SDL_bool GL_OES_framebuffer_object_supported;
+ GLES_FBOList *framebuffers;
+ GLuint window_framebuffer;
+
+ SDL_bool GL_OES_blend_func_separate_supported;
+ SDL_bool GL_OES_blend_equation_separate_supported;
+ SDL_bool GL_OES_blend_subtract_supported;
+
+ GLES_DrawStateCache drawstate;
+} GLES_RenderData;
+
+typedef struct
+{
+ GLuint texture;
+ GLenum type;
+ GLfloat texw;
+ GLfloat texh;
+ GLenum format;
+ GLenum formattype;
+ void *pixels;
+ int pitch;
+ GLES_FBOList *fbo;
+} GLES_TextureData;
+
+static int
+GLES_SetError(const char *prefix, GLenum result)
+{
+ const char *error;
+
+ switch (result) {
+ case GL_NO_ERROR:
+ error = "GL_NO_ERROR";
+ break;
+ case GL_INVALID_ENUM:
+ error = "GL_INVALID_ENUM";
+ break;
+ case GL_INVALID_VALUE:
+ error = "GL_INVALID_VALUE";
+ break;
+ case GL_INVALID_OPERATION:
+ error = "GL_INVALID_OPERATION";
+ break;
+ case GL_STACK_OVERFLOW:
+ error = "GL_STACK_OVERFLOW";
+ break;
+ case GL_STACK_UNDERFLOW:
+ error = "GL_STACK_UNDERFLOW";
+ break;
+ case GL_OUT_OF_MEMORY:
+ error = "GL_OUT_OF_MEMORY";
+ break;
+ default:
+ error = "UNKNOWN";
+ break;
+ }
+ return SDL_SetError("%s: %s", prefix, error);
+}
+
+static int GLES_LoadFunctions(GLES_RenderData * data)
+{
+#if SDL_VIDEO_DRIVER_UIKIT
+#define __SDL_NOGETPROCADDR__
+#elif SDL_VIDEO_DRIVER_ANDROID
+#define __SDL_NOGETPROCADDR__
+#endif
+
+#ifdef __SDL_NOGETPROCADDR__
+#define SDL_PROC(ret,func,params) data->func=func;
+#define SDL_PROC_OES(ret,func,params) data->func=func;
+#else
+#define SDL_PROC(ret,func,params) \
+ do { \
+ data->func = SDL_GL_GetProcAddress(#func); \
+ if ( ! data->func ) { \
+ return SDL_SetError("Couldn't load GLES function %s: %s", #func, SDL_GetError()); \
+ } \
+ } while ( 0 );
+#define SDL_PROC_OES(ret,func,params) \
+ do { \
+ data->func = SDL_GL_GetProcAddress(#func); \
+ } while ( 0 );
+#endif /* __SDL_NOGETPROCADDR__ */
+
+#include "SDL_glesfuncs.h"
+#undef SDL_PROC
+#undef SDL_PROC_OES
+ return 0;
+}
+
+static GLES_FBOList *
+GLES_GetFBO(GLES_RenderData *data, Uint32 w, Uint32 h)
+{
+ GLES_FBOList *result = data->framebuffers;
+ while ((result) && ((result->w != w) || (result->h != h)) ) {
+ result = result->next;
+ }
+ if (result == NULL) {
+ result = SDL_malloc(sizeof(GLES_FBOList));
+ result->w = w;
+ result->h = h;
+ data->glGenFramebuffersOES(1, &result->FBO);
+ result->next = data->framebuffers;
+ data->framebuffers = result;
+ }
+ return result;
+}
+
+
+static int
+GLES_ActivateRenderer(SDL_Renderer * renderer)
+{
+ GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
+
+ if (SDL_GL_GetCurrentContext() != data->context) {
+ if (SDL_GL_MakeCurrent(renderer->window, data->context) < 0) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static void
+GLES_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
+{
+ GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
+
+ if (event->event == SDL_WINDOWEVENT_MINIMIZED) {
+ /* According to Apple documentation, we need to finish drawing NOW! */
+ data->glFinish();
+ }
+}
+
+static int
+GLES_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
+{
+ SDL_GL_GetDrawableSize(renderer->window, w, h);
+ return 0;
+}
+
+static GLenum GetBlendFunc(SDL_BlendFactor factor)
+{
+ switch (factor) {
+ case SDL_BLENDFACTOR_ZERO:
+ return GL_ZERO;
+ case SDL_BLENDFACTOR_ONE:
+ return GL_ONE;
+ case SDL_BLENDFACTOR_SRC_COLOR:
+ return GL_SRC_COLOR;
+ case SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR:
+ return GL_ONE_MINUS_SRC_COLOR;
+ case SDL_BLENDFACTOR_SRC_ALPHA:
+ return GL_SRC_ALPHA;
+ case SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA:
+ return GL_ONE_MINUS_SRC_ALPHA;
+ case SDL_BLENDFACTOR_DST_COLOR:
+ return GL_DST_COLOR;
+ case SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR:
+ return GL_ONE_MINUS_DST_COLOR;
+ case SDL_BLENDFACTOR_DST_ALPHA:
+ return GL_DST_ALPHA;
+ case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA:
+ return GL_ONE_MINUS_DST_ALPHA;
+ default:
+ return GL_INVALID_ENUM;
+ }
+}
+
+static GLenum GetBlendEquation(SDL_BlendOperation operation)
+{
+ switch (operation) {
+ case SDL_BLENDOPERATION_ADD:
+ return GL_FUNC_ADD_OES;
+ case SDL_BLENDOPERATION_SUBTRACT:
+ return GL_FUNC_SUBTRACT_OES;
+ case SDL_BLENDOPERATION_REV_SUBTRACT:
+ return GL_FUNC_REVERSE_SUBTRACT_OES;
+ default:
+ return GL_INVALID_ENUM;
+ }
+}
+
+static SDL_bool
+GLES_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
+{
+ GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
+ SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
+ SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
+ SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
+ SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
+ SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
+ SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
+
+ if (GetBlendFunc(srcColorFactor) == GL_INVALID_ENUM ||
+ GetBlendFunc(srcAlphaFactor) == GL_INVALID_ENUM ||
+ GetBlendEquation(colorOperation) == GL_INVALID_ENUM ||
+ GetBlendFunc(dstColorFactor) == GL_INVALID_ENUM ||
+ GetBlendFunc(dstAlphaFactor) == GL_INVALID_ENUM ||
+ GetBlendEquation(alphaOperation) == GL_INVALID_ENUM) {
+ return SDL_FALSE;
+ }
+ if ((srcColorFactor != srcAlphaFactor || dstColorFactor != dstAlphaFactor) && !data->GL_OES_blend_func_separate_supported) {
+ return SDL_FALSE;
+ }
+ if (colorOperation != alphaOperation && !data->GL_OES_blend_equation_separate_supported) {
+ return SDL_FALSE;
+ }
+ if (colorOperation != SDL_BLENDOPERATION_ADD && !data->GL_OES_blend_subtract_supported) {
+ return SDL_FALSE;
+ }
+ return SDL_TRUE;
+}
+
+static int
+GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+ GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
+ GLES_TextureData *data;
+ GLint internalFormat;
+ GLenum format, type;
+ int texture_w, texture_h;
+ GLenum scaleMode;
+ GLenum result;
+
+ GLES_ActivateRenderer(renderer);
+
+ switch (texture->format) {
+ case SDL_PIXELFORMAT_ABGR8888:
+ internalFormat = GL_RGBA;
+ format = GL_RGBA;
+ type = GL_UNSIGNED_BYTE;
+ break;
+ default:
+ return SDL_SetError("Texture format not supported");
+ }
+
+ data = (GLES_TextureData *) SDL_calloc(1, sizeof(*data));
+ if (!data) {
+ return SDL_OutOfMemory();
+ }
+
+ if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
+ data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
+ data->pixels = SDL_calloc(1, texture->h * data->pitch);
+ if (!data->pixels) {
+ SDL_free(data);
+ return SDL_OutOfMemory();
+ }
+ }
+
+
+ if (texture->access == SDL_TEXTUREACCESS_TARGET) {
+ if (!renderdata->GL_OES_framebuffer_object_supported) {
+ SDL_free(data);
+ return SDL_SetError("GL_OES_framebuffer_object not supported");
+ }
+ data->fbo = GLES_GetFBO(renderer->driverdata, texture->w, texture->h);
+ } else {
+ data->fbo = NULL;
+ }
+
+
+ renderdata->glGetError();
+ renderdata->glEnable(GL_TEXTURE_2D);
+ renderdata->glGenTextures(1, &data->texture);
+ result = renderdata->glGetError();
+ if (result != GL_NO_ERROR) {
+ if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
+ SDL_free(data->pixels);
+ }
+ SDL_free(data);
+ return GLES_SetError("glGenTextures()", result);
+ }
+
+ data->type = GL_TEXTURE_2D;
+ /* no NPOV textures allowed in OpenGL ES (yet) */
+ texture_w = SDL_powerof2(texture->w);
+ texture_h = SDL_powerof2(texture->h);
+ data->texw = (GLfloat) texture->w / texture_w;
+ data->texh = (GLfloat) texture->h / texture_h;
+
+ data->format = format;
+ data->formattype = type;
+ scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
+ renderdata->glBindTexture(data->type, data->texture);
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, scaleMode);
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, scaleMode);
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
+ texture_h, 0, format, type, NULL);
+ renderdata->glDisable(GL_TEXTURE_2D);
+ renderdata->drawstate.texture = texture;
+ renderdata->drawstate.texturing = SDL_FALSE;
+
+ result = renderdata->glGetError();
+ if (result != GL_NO_ERROR) {
+ if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
+ SDL_free(data->pixels);
+ }
+ SDL_free(data);
+ return GLES_SetError("glTexImage2D()", result);
+ }
+
+ texture->driverdata = data;
+ return 0;
+}
+
+static int
+GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * rect, const void *pixels, int pitch)
+{
+ GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
+ GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
+ Uint8 *blob = NULL;
+ Uint8 *src;
+ int srcPitch;
+ int y;
+
+ GLES_ActivateRenderer(renderer);
+
+ /* Bail out if we're supposed to update an empty rectangle */
+ if (rect->w <= 0 || rect->h <= 0) {
+ return 0;
+ }
+
+ /* Reformat the texture data into a tightly packed array */
+ srcPitch = rect->w * SDL_BYTESPERPIXEL(texture->format);
+ src = (Uint8 *)pixels;
+ if (pitch != srcPitch) {
+ blob = (Uint8 *)SDL_malloc(srcPitch * rect->h);
+ if (!blob) {
+ return SDL_OutOfMemory();
+ }
+ src = blob;
+ for (y = 0; y < rect->h; ++y) {
+ SDL_memcpy(src, pixels, srcPitch);
+ src += srcPitch;
+ pixels = (Uint8 *)pixels + pitch;
+ }
+ src = blob;
+ }
+
+ /* Create a texture subimage with the supplied data */
+ renderdata->glGetError();
+ renderdata->glEnable(data->type);
+ renderdata->glBindTexture(data->type, data->texture);
+ renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ renderdata->glTexSubImage2D(data->type,
+ 0,
+ rect->x,
+ rect->y,
+ rect->w,
+ rect->h,
+ data->format,
+ data->formattype,
+ src);
+ renderdata->glDisable(data->type);
+ SDL_free(blob);
+
+ renderdata->drawstate.texture = texture;
+ renderdata->drawstate.texturing = SDL_FALSE;
+
+ if (renderdata->glGetError() != GL_NO_ERROR) {
+ return SDL_SetError("Failed to update texture");
+ }
+ return 0;
+}
+
+static int
+GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * rect, void **pixels, int *pitch)
+{
+ GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
+
+ *pixels =
+ (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
+ rect->x * SDL_BYTESPERPIXEL(texture->format));
+ *pitch = data->pitch;
+ return 0;
+}
+
+static void
+GLES_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+ GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
+ SDL_Rect rect;
+
+ /* We do whole texture updates, at least for now */
+ rect.x = 0;
+ rect.y = 0;
+ rect.w = texture->w;
+ rect.h = texture->h;
+ GLES_UpdateTexture(renderer, texture, &rect, data->pixels, data->pitch);
+}
+
+static void
+GLES_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture, SDL_ScaleMode scaleMode)
+{
+ GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
+ GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
+ GLenum glScaleMode = (scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
+
+ renderdata->glBindTexture(data->type, data->texture);
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, glScaleMode);
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, glScaleMode);
+}
+
+static int
+GLES_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+ GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
+ GLES_TextureData *texturedata = NULL;
+ GLenum status;
+
+ if (!data->GL_OES_framebuffer_object_supported) {
+ return SDL_SetError("Can't enable render target support in this renderer");
+ }
+
+ data->drawstate.viewport_dirty = SDL_TRUE;
+
+ if (texture == NULL) {
+ data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, data->window_framebuffer);
+ return 0;
+ }
+
+ texturedata = (GLES_TextureData *) texture->driverdata;
+ data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, texturedata->fbo->FBO);
+ /* TODO: check if texture pixel format allows this operation */
+ data->glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, texturedata->type, texturedata->texture, 0);
+ /* Check FBO status */
+ status = data->glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
+ if (status != GL_FRAMEBUFFER_COMPLETE_OES) {
+ return SDL_SetError("glFramebufferTexture2DOES() failed");
+ }
+ return 0;
+}
+
+
+static int
+GLES_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
+{
+ return 0; /* nothing to do in this backend. */
+}
+
+static int
+GLES_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
+{
+ GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 2 * sizeof (GLfloat), 0, &cmd->data.draw.first);
+ int i;
+
+ if (!verts) {
+ return -1;
+ }
+
+ cmd->data.draw.count = count;
+ for (i = 0; i < count; i++) {
+ *(verts++) = 0.5f + points[i].x;
+ *(verts++) = 0.5f + points[i].y;
+ }
+
+ return 0;
+}
+
+static int
+GLES_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
+{
+ int i;
+ GLfloat prevx, prevy;
+ const size_t vertlen = (sizeof (GLfloat) * 2) * count;
+ GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, vertlen, 0, &cmd->data.draw.first);
+
+ if (!verts) {
+ return -1;
+ }
+ cmd->data.draw.count = count;
+
+ /* 0.5f offset to hit the center of the pixel. */
+ prevx = 0.5f + points->x;
+ prevy = 0.5f + points->y;
+ *(verts++) = prevx;
+ *(verts++) = prevy;
+
+ /* bump the end of each line segment out a quarter of a pixel, to provoke
+ the diamond-exit rule. Without this, you won't just drop the last
+ pixel of the last line segment, but you might also drop pixels at the
+ edge of any given line segment along the way too. */
+ for (i = 1; i < count; i++) {
+ const GLfloat xstart = prevx;
+ const GLfloat ystart = prevy;
+ const GLfloat xend = points[i].x + 0.5f; /* 0.5f to hit pixel center. */
+ const GLfloat yend = points[i].y + 0.5f;
+ /* bump a little in the direction we are moving in. */
+ const GLfloat deltax = xend - xstart;
+ const GLfloat deltay = yend - ystart;
+ const GLfloat angle = SDL_atan2f(deltay, deltax);
+ prevx = xend + (SDL_cosf(angle) * 0.25f);
+ prevy = yend + (SDL_sinf(angle) * 0.25f);
+ *(verts++) = prevx;
+ *(verts++) = prevy;
+ }
+
+ return 0;
+}
+
+static int
+GLES_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture,
+ const float *xy, int xy_stride, const SDL_Color *color, int color_stride, const float *uv, int uv_stride,
+ int num_vertices, const void *indices, int num_indices, int size_indices,
+ float scale_x, float scale_y)
+{
+ GLES_TextureData *texturedata = NULL;
+ int i;
+ int count = indices ? num_indices : num_vertices;
+ GLfloat *verts;
+ int sz = 2 + 4 + (texture ? 2 : 0);
+
+ verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * sz * sizeof (GLfloat), 0, &cmd->data.draw.first);
+ if (!verts) {
+ return -1;
+ }
+
+ if (texture) {
+ texturedata = (GLES_TextureData *) texture->driverdata;
+ }
+
+ cmd->data.draw.count = count;
+ size_indices = indices ? size_indices : 0;
+
+ for (i = 0; i < count; i++) {
+ int j;
+ float *xy_;
+ SDL_Color col_;
+ if (size_indices == 4) {
+ j = ((const Uint32 *)indices)[i];
+ } else if (size_indices == 2) {
+ j = ((const Uint16 *)indices)[i];
+ } else if (size_indices == 1) {
+ j = ((const Uint8 *)indices)[i];
+ } else {
+ j = i;
+ }
+
+ xy_ = (float *)((char*)xy + j * xy_stride);
+ col_ = *(SDL_Color *)((char*)color + j * color_stride);
+
+ *(verts++) = xy_[0] * scale_x;
+ *(verts++) = xy_[1] * scale_y;
+
+ *(verts++) = col_.r * inv255f;
+ *(verts++) = col_.g * inv255f;
+ *(verts++) = col_.b * inv255f;
+ *(verts++) = col_.a * inv255f;
+
+ if (texture) {
+ float *uv_ = (float *)((char*)uv + j * uv_stride);
+ *(verts++) = uv_[0] * texturedata->texw;
+ *(verts++) = uv_[1] * texturedata->texh;
+ }
+ }
+ return 0;
+}
+
+static void
+SetDrawState(GLES_RenderData *data, const SDL_RenderCommand *cmd)
+{
+ const SDL_BlendMode blend = cmd->data.draw.blend;
+ const Uint8 r = cmd->data.draw.r;
+ const Uint8 g = cmd->data.draw.g;
+ const Uint8 b = cmd->data.draw.b;
+ const Uint8 a = cmd->data.draw.a;
+ const Uint32 color = (((Uint32)a << 24) | (r << 16) | (g << 8) | b);
+
+ if (color != data->drawstate.color) {
+ const GLfloat fr = ((GLfloat) r) * inv255f;
+ const GLfloat fg = ((GLfloat) g) * inv255f;
+ const GLfloat fb = ((GLfloat) b) * inv255f;
+ const GLfloat fa = ((GLfloat) a) * inv255f;
+ data->glColor4f(fr, fg, fb, fa);
+ data->drawstate.color = color;
+ }
+
+ if (data->drawstate.viewport_dirty) {
+ const SDL_Rect *viewport = &data->drawstate.viewport;
+ const SDL_bool istarget = (data->drawstate.target != NULL);
+ data->glMatrixMode(GL_PROJECTION);
+ data->glLoadIdentity();
+ data->glViewport(viewport->x,
+ istarget ? viewport->y : (data->drawstate.drawableh - viewport->y - viewport->h),
+ viewport->w, viewport->h);
+ if (viewport->w && viewport->h) {
+ data->glOrthof((GLfloat) 0, (GLfloat) viewport->w,
+ (GLfloat) (istarget ? 0 : viewport->h),
+ (GLfloat) (istarget ? viewport->h : 0),
+ 0.0, 1.0);
+ }
+ data->glMatrixMode(GL_MODELVIEW);
+ data->drawstate.viewport_dirty = SDL_FALSE;
+ }
+
+ if (data->drawstate.cliprect_enabled_dirty) {
+ if (data->drawstate.cliprect_enabled) {
+ data->glEnable(GL_SCISSOR_TEST);
+ } else {
+ data->glDisable(GL_SCISSOR_TEST);
+ }
+ data->drawstate.cliprect_enabled_dirty = SDL_FALSE;
+ }
+
+ if (data->drawstate.cliprect_enabled && data->drawstate.cliprect_dirty) {
+ const SDL_Rect *viewport = &data->drawstate.viewport;
+ const SDL_Rect *rect = &data->drawstate.cliprect;
+ const SDL_bool istarget = (data->drawstate.target != NULL);
+ data->glScissor(viewport->x + rect->x,
+ istarget ? viewport->y + rect->y : data->drawstate.drawableh - viewport->y - rect->y - rect->h,
+ rect->w, rect->h);
+ data->drawstate.cliprect_dirty = SDL_FALSE;
+ }
+
+ if (blend != data->drawstate.blend) {
+ if (blend == SDL_BLENDMODE_NONE) {
+ data->glDisable(GL_BLEND);
+ } else {
+ data->glEnable(GL_BLEND);
+ if (data->GL_OES_blend_func_separate_supported) {
+ data->glBlendFuncSeparateOES(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)),
+ GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)),
+ GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blend)),
+ GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blend)));
+ } else {
+ data->glBlendFunc(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)),
+ GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)));
+ }
+ if (data->GL_OES_blend_equation_separate_supported) {
+ data->glBlendEquationSeparateOES(GetBlendEquation(SDL_GetBlendModeColorOperation(blend)),
+ GetBlendEquation(SDL_GetBlendModeAlphaOperation(blend)));
+ } else if (data->GL_OES_blend_subtract_supported) {
+ data->glBlendEquationOES(GetBlendEquation(SDL_GetBlendModeColorOperation(blend)));
+ }
+ }
+ data->drawstate.blend = blend;
+ }
+
+ if ((cmd->data.draw.texture != NULL) != data->drawstate.texturing) {
+ if (cmd->data.draw.texture == NULL) {
+ data->glDisable(GL_TEXTURE_2D);
+ data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ data->drawstate.texturing = SDL_FALSE;
+ } else {
+ data->glEnable(GL_TEXTURE_2D);
+ data->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ data->drawstate.texturing = SDL_TRUE;
+ }
+ }
+}
+
+static void
+SetCopyState(GLES_RenderData *data, const SDL_RenderCommand *cmd)
+{
+ SDL_Texture *texture = cmd->data.draw.texture;
+ SetDrawState(data, cmd);
+
+ if (texture != data->drawstate.texture) {
+ GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
+ data->glBindTexture(GL_TEXTURE_2D, texturedata->texture);
+ data->drawstate.texture = texture;
+ }
+}
+
+static int
+GLES_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
+{
+ GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
+
+ if (GLES_ActivateRenderer(renderer) < 0) {
+ return -1;
+ }
+
+ data->drawstate.target = renderer->target;
+
+ if (!renderer->target) {
+ int w, h;
+ SDL_GL_GetDrawableSize(renderer->window, &w, &h);
+ if ((w != data->drawstate.drawablew) || (h != data->drawstate.drawableh)) {
+ data->drawstate.viewport_dirty = SDL_TRUE; // if the window dimensions changed, invalidate the current viewport, etc.
+ data->drawstate.cliprect_dirty = SDL_TRUE;
+ data->drawstate.drawablew = w;
+ data->drawstate.drawableh = h;
+ }
+
+ }
+
+ while (cmd) {
+ switch (cmd->command) {
+ case SDL_RENDERCMD_SETDRAWCOLOR: {
+ break; /* not used in this render backend. */
+ }
+
+ case SDL_RENDERCMD_SETVIEWPORT: {
+ SDL_Rect *viewport = &data->drawstate.viewport;
+ if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof(cmd->data.viewport.rect)) != 0) {
+ SDL_copyp(viewport, &cmd->data.viewport.rect);
+ data->drawstate.viewport_dirty = SDL_TRUE;
+ }
+ break;
+ }
+
+ case SDL_RENDERCMD_SETCLIPRECT: {
+ const SDL_Rect *rect = &cmd->data.cliprect.rect;
+ if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) {
+ data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
+ data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
+ }
+ if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof(*rect)) != 0) {
+ SDL_copyp(&data->drawstate.cliprect, rect);
+ data->drawstate.cliprect_dirty = SDL_TRUE;
+ }
+ break;
+ }
+
+ case SDL_RENDERCMD_CLEAR: {
+ const Uint8 r = cmd->data.color.r;
+ const Uint8 g = cmd->data.color.g;
+ const Uint8 b = cmd->data.color.b;
+ const Uint8 a = cmd->data.color.a;
+ const Uint32 color = (((Uint32)a << 24) | (r << 16) | (g << 8) | b);
+ if (color != data->drawstate.clear_color) {
+ const GLfloat fr = ((GLfloat) r) * inv255f;
+ const GLfloat fg = ((GLfloat) g) * inv255f;
+ const GLfloat fb = ((GLfloat) b) * inv255f;
+ const GLfloat fa = ((GLfloat) a) * inv255f;
+ data->glClearColor(fr, fg, fb, fa);
+ data->drawstate.clear_color = color;
+ }
+
+ if (data->drawstate.cliprect_enabled || data->drawstate.cliprect_enabled_dirty) {
+ data->glDisable(GL_SCISSOR_TEST);
+ data->drawstate.cliprect_enabled_dirty = data->drawstate.cliprect_enabled;
+ }
+
+ data->glClear(GL_COLOR_BUFFER_BIT);
+
+ break;
+ }
+
+ case SDL_RENDERCMD_DRAW_POINTS: {
+ const size_t count = cmd->data.draw.count;
+ const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
+ SetDrawState(data, cmd);
+ data->glVertexPointer(2, GL_FLOAT, 0, verts);
+ data->glDrawArrays(GL_POINTS, 0, (GLsizei) count);
+ break;
+ }
+
+ case SDL_RENDERCMD_DRAW_LINES: {
+ const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
+ const size_t count = cmd->data.draw.count;
+ SDL_assert(count >= 2);
+ SetDrawState(data, cmd);
+ data->glVertexPointer(2, GL_FLOAT, 0, verts);
+ data->glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) count);
+ break;
+ }
+
+ case SDL_RENDERCMD_FILL_RECTS: /* unused */
+ break;
+
+ case SDL_RENDERCMD_COPY: /* unused */
+ break;
+
+ case SDL_RENDERCMD_COPY_EX: /* unused */
+ break;
+
+ case SDL_RENDERCMD_GEOMETRY: {
+ const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
+ SDL_Texture *texture = cmd->data.draw.texture;
+ const size_t count = cmd->data.draw.count;
+ int stride = (2 + 4 + (texture ? 2 : 0)) * sizeof (float);
+
+ if (texture) {
+ SetCopyState(data, cmd);
+ } else {
+ SetDrawState(data, cmd);
+ }
+
+ data->glEnableClientState(GL_COLOR_ARRAY);
+
+ data->glVertexPointer(2, GL_FLOAT, stride, verts);
+ data->glColorPointer(4, GL_FLOAT, stride, verts + 2);
+ if (texture) {
+ data->glTexCoordPointer(2, GL_FLOAT, stride, verts + 2 + 4);
+ }
+
+ data->glDrawArrays(GL_TRIANGLES, 0, (GLsizei) count);
+
+ data->glDisableClientState(GL_COLOR_ARRAY);
+ break;
+ }
+
+ case SDL_RENDERCMD_NO_OP:
+ break;
+ }
+
+ cmd = cmd->next;
+ }
+
+ return 0;
+}
+
+static int
+GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
+ Uint32 pixel_format, void * pixels, int pitch)
+{
+ GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
+ Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ABGR8888;
+ void *temp_pixels;
+ int temp_pitch;
+ Uint8 *src, *dst, *tmp;
+ int w, h, length, rows;
+ int status;
+
+ GLES_ActivateRenderer(renderer);
+
+ temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format);
+ temp_pixels = SDL_malloc(rect->h * temp_pitch);
+ if (!temp_pixels) {
+ return SDL_OutOfMemory();
+ }
+
+ SDL_GetRendererOutputSize(renderer, &w, &h);
+
+ data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
+
+ data->glReadPixels(rect->x, renderer->target ? rect->y : (h-rect->y)-rect->h,
+ rect->w, rect->h, GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels);
+
+ /* Flip the rows to be top-down if necessary */
+ if (!renderer->target) {
+ SDL_bool isstack;
+ length = rect->w * SDL_BYTESPERPIXEL(temp_format);
+ src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
+ dst = (Uint8*)temp_pixels;
+ tmp = SDL_small_alloc(Uint8, length, &isstack);
+ rows = rect->h / 2;
+ while (rows--) {
+ SDL_memcpy(tmp, dst, length);
+ SDL_memcpy(dst, src, length);
+ SDL_memcpy(src, tmp, length);
+ dst += temp_pitch;
+ src -= temp_pitch;
+ }
+ SDL_small_free(tmp, isstack);
+ }
+
+ status = SDL_ConvertPixels(rect->w, rect->h,
+ temp_format, temp_pixels, temp_pitch,
+ pixel_format, pixels, pitch);
+ SDL_free(temp_pixels);
+
+ return status;
+}
+
+static int
+GLES_RenderPresent(SDL_Renderer * renderer)
+{
+ GLES_ActivateRenderer(renderer);
+
+ return SDL_GL_SwapWindowWithResult(renderer->window);
+}
+
+static void
+GLES_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+ GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
+
+ GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
+
+ GLES_ActivateRenderer(renderer);
+
+ if (renderdata->drawstate.texture == texture) {
+ renderdata->drawstate.texture = NULL;
+ }
+ if (renderdata->drawstate.target == texture) {
+ renderdata->drawstate.target = NULL;
+ }
+
+ if (!data) {
+ return;
+ }
+ if (data->texture) {
+ renderdata->glDeleteTextures(1, &data->texture);
+ }
+ SDL_free(data->pixels);
+ SDL_free(data);
+ texture->driverdata = NULL;
+}
+
+static void
+GLES_DestroyRenderer(SDL_Renderer * renderer)
+{
+ GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
+
+ if (data) {
+ if (data->context) {
+ while (data->framebuffers) {
+ GLES_FBOList *nextnode = data->framebuffers->next;
+ data->glDeleteFramebuffersOES(1, &data->framebuffers->FBO);
+ SDL_free(data->framebuffers);
+ data->framebuffers = nextnode;
+ }
+ SDL_GL_DeleteContext(data->context);
+ }
+ SDL_free(data);
+ }
+ SDL_free(renderer);
+}
+
+static int GLES_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh)
+{
+ GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
+ GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
+ GLES_ActivateRenderer(renderer);
+
+ data->glEnable(GL_TEXTURE_2D);
+ data->glBindTexture(texturedata->type, texturedata->texture);
+
+ data->drawstate.texture = texture;
+ data->drawstate.texturing = SDL_TRUE;
+
+ if (texw) {
+ *texw = (float)texturedata->texw;
+ }
+ if (texh) {
+ *texh = (float)texturedata->texh;
+ }
+
+ return 0;
+}
+
+static int GLES_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture)
+{
+ GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
+ GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
+ GLES_ActivateRenderer(renderer);
+ data->glDisable(texturedata->type);
+
+ data->drawstate.texture = NULL;
+ data->drawstate.texturing = SDL_FALSE;
+
+ return 0;
+}
+
+static int
+GLES_SetVSync(SDL_Renderer * renderer, const int vsync)
+{
+ int retval;
+ if (vsync) {
+ retval = SDL_GL_SetSwapInterval(1);
+ } else {
+ retval = SDL_GL_SetSwapInterval(0);
+ }
+ if (retval != 0) {
+ return retval;
+ }
+ if (SDL_GL_GetSwapInterval() > 0) {
+ renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
+ } else {
+ renderer->info.flags &= ~SDL_RENDERER_PRESENTVSYNC;
+ }
+ return retval;
+}
+
+
+static SDL_Renderer *
+GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
+{
+ SDL_Renderer *renderer;
+ GLES_RenderData *data;
+ GLint value;
+ Uint32 window_flags;
+ int profile_mask = 0, major = 0, minor = 0;
+ SDL_bool changed_window = SDL_FALSE;
+
+ SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask);
+ SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
+ SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
+
+ window_flags = SDL_GetWindowFlags(window);
+ if (!(window_flags & SDL_WINDOW_OPENGL) ||
+ profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) {
+
+ changed_window = SDL_TRUE;
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);
+
+ if (SDL_RecreateWindow(window, (window_flags & ~(SDL_WINDOW_VULKAN | SDL_WINDOW_METAL)) | SDL_WINDOW_OPENGL) < 0) {
+ goto error;
+ }
+ }
+
+ renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
+ if (!renderer) {
+ SDL_OutOfMemory();
+ goto error;
+ }
+
+ data = (GLES_RenderData *) SDL_calloc(1, sizeof(*data));
+ if (!data) {
+ GLES_DestroyRenderer(renderer);
+ SDL_OutOfMemory();
+ goto error;
+ }
+
+ renderer->WindowEvent = GLES_WindowEvent;
+ renderer->GetOutputSize = GLES_GetOutputSize;
+ renderer->SupportsBlendMode = GLES_SupportsBlendMode;
+ renderer->CreateTexture = GLES_CreateTexture;
+ renderer->UpdateTexture = GLES_UpdateTexture;
+ renderer->LockTexture = GLES_LockTexture;
+ renderer->UnlockTexture = GLES_UnlockTexture;
+ renderer->SetTextureScaleMode = GLES_SetTextureScaleMode;
+ renderer->SetRenderTarget = GLES_SetRenderTarget;
+ renderer->QueueSetViewport = GLES_QueueSetViewport;
+ renderer->QueueSetDrawColor = GLES_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
+ renderer->QueueDrawPoints = GLES_QueueDrawPoints;
+ renderer->QueueDrawLines = GLES_QueueDrawLines;
+ renderer->QueueGeometry = GLES_QueueGeometry;
+ renderer->RunCommandQueue = GLES_RunCommandQueue;
+ renderer->RenderReadPixels = GLES_RenderReadPixels;
+ renderer->RenderPresent = GLES_RenderPresent;
+ renderer->DestroyTexture = GLES_DestroyTexture;
+ renderer->DestroyRenderer = GLES_DestroyRenderer;
+ renderer->SetVSync = GLES_SetVSync;
+ renderer->GL_BindTexture = GLES_BindTexture;
+ renderer->GL_UnbindTexture = GLES_UnbindTexture;
+ renderer->info = GLES_RenderDriver.info;
+ renderer->info.flags = SDL_RENDERER_ACCELERATED;
+ renderer->driverdata = data;
+ renderer->window = window;
+
+ data->context = SDL_GL_CreateContext(window);
+ if (!data->context) {
+ GLES_DestroyRenderer(renderer);
+ goto error;
+ }
+ if (SDL_GL_MakeCurrent(window, data->context) < 0) {
+ GLES_DestroyRenderer(renderer);
+ goto error;
+ }
+
+ if (GLES_LoadFunctions(data) < 0) {
+ GLES_DestroyRenderer(renderer);
+ goto error;
+ }
+
+ if (flags & SDL_RENDERER_PRESENTVSYNC) {
+ SDL_GL_SetSwapInterval(1);
+ } else {
+ SDL_GL_SetSwapInterval(0);
+ }
+ if (SDL_GL_GetSwapInterval() > 0) {
+ renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
+ }
+
+ value = 0;
+ data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
+ renderer->info.max_texture_width = value;
+ value = 0;
+ data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
+ renderer->info.max_texture_height = value;
+
+ /* Android does not report GL_OES_framebuffer_object but the functionality seems to be there anyway */
+ if (SDL_GL_ExtensionSupported("GL_OES_framebuffer_object") || data->glGenFramebuffersOES) {
+ data->GL_OES_framebuffer_object_supported = SDL_TRUE;
+ renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE;
+
+ value = 0;
+ data->glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &value);
+ data->window_framebuffer = (GLuint)value;
+ }
+ data->framebuffers = NULL;
+
+ if (SDL_GL_ExtensionSupported("GL_OES_blend_func_separate")) {
+ data->GL_OES_blend_func_separate_supported = SDL_TRUE;
+ }
+ if (SDL_GL_ExtensionSupported("GL_OES_blend_equation_separate")) {
+ data->GL_OES_blend_equation_separate_supported = SDL_TRUE;
+ }
+ if (SDL_GL_ExtensionSupported("GL_OES_blend_subtract")) {
+ data->GL_OES_blend_subtract_supported = SDL_TRUE;
+ }
+
+ /* Set up parameters for rendering */
+ data->glDisable(GL_DEPTH_TEST);
+ data->glDisable(GL_CULL_FACE);
+
+ data->glMatrixMode(GL_MODELVIEW);
+ data->glLoadIdentity();
+
+ data->glEnableClientState(GL_VERTEX_ARRAY);
+ data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ data->glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+
+ data->drawstate.blend = SDL_BLENDMODE_INVALID;
+ data->drawstate.color = 0xFFFFFFFF;
+ data->drawstate.clear_color = 0xFFFFFFFF;
+
+ return renderer;
+
+error:
+ if (changed_window) {
+ /* Uh oh, better try to put it back... */
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
+ SDL_RecreateWindow(window, window_flags);
+ }
+ return NULL;
+}
+
+SDL_RenderDriver GLES_RenderDriver = {
+ GLES_CreateRenderer,
+ {
+ "opengles",
+ (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
+ 1,
+ {SDL_PIXELFORMAT_ABGR8888},
+ 0,
+ 0
+ }
+};
+
+#endif /* SDL_VIDEO_RENDER_OGL_ES && !SDL_RENDER_DISABLED */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h
index 1e9e6b8f3..d5a2f0022 100644
--- a/src/video/SDL_sysvideo.h
+++ b/src/video/SDL_sysvideo.h
@@ -431,7 +431,7 @@ struct SDL_VideoDevice
struct SDL_EGL_VideoData *egl_data;
#endif
-#if SDL_VIDEO_OPENGL_ES2
+#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
struct SDL_PrivateGLESData *gles_data;
#endif
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 3449c6f28..9839c580b 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -37,6 +37,10 @@
#include "SDL_opengl.h"
#endif /* SDL_VIDEO_OPENGL */
+#if SDL_VIDEO_OPENGL_ES && !SDL_VIDEO_OPENGL
+#include "SDL_opengles.h"
+#endif /* SDL_VIDEO_OPENGL_ES && !SDL_VIDEO_OPENGL */
+
/* GL and GLES2 headers conflict on Linux 32 bits */
#if SDL_VIDEO_OPENGL_ES2 && !SDL_VIDEO_OPENGL
#include "SDL_opengles2.h"
@@ -3436,7 +3440,7 @@ SDL_GL_UnloadLibrary(void)
}
}
-#if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES2
+#if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
static SDL_INLINE SDL_bool
isAtLeastGL3(const char *verstr)
{
@@ -3447,7 +3451,7 @@ isAtLeastGL3(const char *verstr)
SDL_bool
SDL_GL_ExtensionSupported(const char *extension)
{
-#if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES2
+#if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
const GLubyte *(APIENTRY * glGetStringFunc) (GLenum);
const char *extensions;
const char *start;
@@ -3539,7 +3543,7 @@ SDL_GL_DeduceMaxSupportedESProfile(int* major, int* minor)
{
/* THIS REQUIRES AN EXISTING GL CONTEXT THAT HAS BEEN MADE CURRENT. */
/* Please refer to https://bugzilla.libsdl.org/show_bug.cgi?id=3725 for discussion. */
-#if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES2
+#if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
/* XXX This is fragile; it will break in the event of release of
* new versions of OpenGL ES.
*/
@@ -3593,6 +3597,10 @@ SDL_GL_ResetAttributes()
_this->gl_config.major_version = 2;
_this->gl_config.minor_version = 0;
_this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES;
+#elif SDL_VIDEO_OPENGL_ES
+ _this->gl_config.major_version = 1;
+ _this->gl_config.minor_version = 1;
+ _this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES;
#endif
if (_this->GL_DefaultProfileConfig) {
@@ -3613,7 +3621,7 @@ SDL_GL_ResetAttributes()
int
SDL_GL_SetAttribute(SDL_GLattr attr, int value)
{
-#if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES2
+#if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
int retval;
if (!_this) {
@@ -3737,7 +3745,7 @@ SDL_GL_SetAttribute(SDL_GLattr attr, int value)
int
SDL_GL_GetAttribute(SDL_GLattr attr, int *value)
{
-#if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES2
+#if SDL_VIDEO_OPENGL || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
GLenum (APIENTRY *glGetErrorFunc) (void);
GLenum attrib = 0;
GLenum error = 0;
diff --git a/src/video/uikit/SDL_uikitevents.m b/src/video/uikit/SDL_uikitevents.m
index aec2adf29..e1bc5a29e 100644
--- a/src/video/uikit/SDL_uikitevents.m
+++ b/src/video/uikit/SDL_uikitevents.m
@@ -148,7 +148,7 @@ UIKit_PumpEvents(_THIS)
} while(result == kCFRunLoopRunHandledSource);
/* See the comment in the function definition. */
-#if SDL_VIDEO_OPENGL_ES2
+#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
UIKit_GL_RestoreCurrentContext();
#endif
}
diff --git a/src/video/uikit/SDL_uikitopengles.h b/src/video/uikit/SDL_uikitopengles.h
index 549904080..c2e6d571c 100644
--- a/src/video/uikit/SDL_uikitopengles.h
+++ b/src/video/uikit/SDL_uikitopengles.h
@@ -21,7 +21,7 @@
#ifndef SDL_uikitopengles_
#define SDL_uikitopengles_
-#if SDL_VIDEO_OPENGL_ES2
+#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
#include "../SDL_sysvideo.h"
@@ -37,7 +37,7 @@ extern int UIKit_GL_LoadLibrary(_THIS, const char *path);
extern void UIKit_GL_RestoreCurrentContext(void);
-#endif /* SDL_VIDEO_OPENGL_ES2 */
+#endif // SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
#endif /* SDL_uikitopengles_ */
diff --git a/src/video/uikit/SDL_uikitopengles.m b/src/video/uikit/SDL_uikitopengles.m
index e557e01a2..15ea2e350 100644
--- a/src/video/uikit/SDL_uikitopengles.m
+++ b/src/video/uikit/SDL_uikitopengles.m
@@ -20,7 +20,7 @@
*/
#include "../../SDL_internal.h"
-#if SDL_VIDEO_DRIVER_UIKIT && SDL_VIDEO_OPENGL_ES2
+#if SDL_VIDEO_DRIVER_UIKIT && (SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2)
#include "SDL_uikitopengles.h"
#import "SDL_uikitopenglview.h"
diff --git a/src/video/uikit/SDL_uikitopenglview.h b/src/video/uikit/SDL_uikitopenglview.h
index f9bc35304..df659a1f1 100644
--- a/src/video/uikit/SDL_uikitopenglview.h
+++ b/src/video/uikit/SDL_uikitopenglview.h
@@ -19,7 +19,7 @@
3. This notice may not be removed or altered from any source distribution.
*/
-#if SDL_VIDEO_OPENGL_ES2
+#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
#import
#import
@@ -59,6 +59,6 @@
@end
-#endif /* SDL_VIDEO_OPENGL_ES2 */
+#endif // SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/uikit/SDL_uikitopenglview.m b/src/video/uikit/SDL_uikitopenglview.m
index 6b4935e44..ea4db411a 100644
--- a/src/video/uikit/SDL_uikitopenglview.m
+++ b/src/video/uikit/SDL_uikitopenglview.m
@@ -20,7 +20,7 @@
*/
#include "../../SDL_internal.h"
-#if SDL_VIDEO_DRIVER_UIKIT && SDL_VIDEO_OPENGL_ES2
+#if SDL_VIDEO_DRIVER_UIKIT && (SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2)
#include
#include
diff --git a/src/video/uikit/SDL_uikitvideo.m b/src/video/uikit/SDL_uikitvideo.m
index 95384a79f..4e8a57755 100644
--- a/src/video/uikit/SDL_uikitvideo.m
+++ b/src/video/uikit/SDL_uikitvideo.m
@@ -113,7 +113,7 @@ UIKit_CreateDevice(void)
device->HasClipboardText = UIKit_HasClipboardText;
/* OpenGL (ES) functions */
-#if SDL_VIDEO_OPENGL_ES2
+#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
device->GL_MakeCurrent = UIKit_GL_MakeCurrent;
device->GL_GetDrawableSize = UIKit_GL_GetDrawableSize;
device->GL_SwapWindow = UIKit_GL_SwapWindow;
diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m
index 574c79627..ee7ee83b0 100644
--- a/src/video/uikit/SDL_uikitviewcontroller.m
+++ b/src/video/uikit/SDL_uikitviewcontroller.m
@@ -176,7 +176,7 @@ SDL_HideHomeIndicatorHintChanged(void *userdata, const char *name, const char *o
/* Don't run the game loop while a messagebox is up */
if (!UIKit_ShowingMessageBox()) {
/* See the comment in the function definition. */
-#if SDL_VIDEO_OPENGL_ES2
+#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
UIKit_GL_RestoreCurrentContext();
#endif
diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m
index a1ee71229..7b8dfff56 100644
--- a/src/video/uikit/SDL_uikitwindow.m
+++ b/src/video/uikit/SDL_uikitwindow.m
@@ -404,7 +404,7 @@ UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
/* These struct members were added in SDL 2.0.4. */
if (versionnum >= SDL_VERSIONNUM(2,0,4)) {
-#if SDL_VIDEO_OPENGL_ES2
+#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
if ([data.viewcontroller.view isKindOfClass:[SDL_uikitopenglview class]]) {
SDL_uikitopenglview *glview = (SDL_uikitopenglview *)data.viewcontroller.view;
info->info.uikit.framebuffer = glview.drawableFramebuffer;
diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c
index d575ce2c1..6d4e53f20 100644
--- a/src/video/x11/SDL_x11window.c
+++ b/src/video/x11/SDL_x11window.c
@@ -648,7 +648,7 @@ X11_CreateWindow(_THIS, SDL_Window * window)
}
windowdata = (SDL_WindowData *) window->driverdata;
-#if SDL_VIDEO_OPENGL_ES2 || SDL_VIDEO_OPENGL_EGL
+#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2 || SDL_VIDEO_OPENGL_EGL
if ((window->flags & SDL_WINDOW_OPENGL) &&
((_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) ||
SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_FORCE_EGL, SDL_FALSE))
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index feb040d42..8afa14f47 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -125,6 +125,7 @@ add_sdl_test_executable(testgamecontroller NEEDS_RESOURCES testgamecontroller.c
add_sdl_test_executable(testgeometry testgeometry.c testutils.c)
add_sdl_test_executable(testgesture testgesture.c)
add_sdl_test_executable(testgl2 testgl2.c)
+add_sdl_test_executable(testgles testgles.c)
add_sdl_test_executable(testgles2 testgles2.c)
add_sdl_test_executable(testhaptic testhaptic.c)
add_sdl_test_executable(testhotplug testhotplug.c)
diff --git a/test/Makefile.in b/test/Makefile.in
index 3c56a1e5c..aae311280 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -84,6 +84,7 @@ TARGETS = \
@OPENGL_TARGETS@ += testgl2$(EXE) testshader$(EXE)
+@OPENGLES1_TARGETS@ += testgles$(EXE)
@OPENGLES2_TARGETS@ += testgles2$(EXE)
@@ -207,6 +208,9 @@ testgesture$(EXE): $(srcdir)/testgesture.c
testgl2$(EXE): $(srcdir)/testgl2.c
$(CC) -o $@ $^ $(CFLAGS) $(LIBS) @MATHLIB@
+testgles$(EXE): $(srcdir)/testgles.c
+ $(CC) -o $@ $^ $(CFLAGS) $(LIBS) @GLESLIB@ @MATHLIB@
+
testgles2$(EXE): $(srcdir)/testgles2.c
$(CC) -o $@ $^ $(CFLAGS) $(LIBS) @MATHLIB@
diff --git a/test/configure b/test/configure
index f7e17aca2..93512a2fa 100755
--- a/test/configure
+++ b/test/configure
@@ -624,6 +624,7 @@ GLESLIB
GLLIB
OPENGL_TARGETS
OPENGLES2_TARGETS
+OPENGLES1_TARGETS
CPP
XMKMF
SDL3_CONFIG
@@ -4573,6 +4574,33 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_opengl" >&5
printf "%s\n" "$have_opengl" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OpenGL ES support" >&5
+printf %s "checking for OpenGL ES support... " >&6; }
+have_opengles=no
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include "SDL_opengles.h"
+ #ifndef SDL_VIDEO_OPENGL_ES
+ #error SDL_VIDEO_OPENGL_ES
+ #endif
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ have_opengles=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_opengles" >&5
+printf "%s\n" "$have_opengles" >&6; }
+
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OpenGL ES2 support" >&5
printf %s "checking for OpenGL ES2 support... " >&6; }
have_opengles2=no
@@ -4603,8 +4631,14 @@ printf "%s\n" "$have_opengles2" >&6; }
GLLIB=""
GLESLIB=""
GLES2LIB=""
+OPENGLES1_TARGETS="UNUSED"
OPENGLES2_TARGETS="UNUSED"
OPENGL_TARGETS="UNUSED"
+if test x$have_opengles = xyes; then
+ CFLAGS="$CFLAGS -DHAVE_OPENGLES"
+ GLESLIB="$XPATH -lGLESv1_CM"
+ OPENGLES1_TARGETS="TARGETS"
+fi
if test x$have_opengles2 = xyes; then
CFLAGS="$CFLAGS -DHAVE_OPENGLES2"
#GLES2LIB="$XPATH -lGLESv2"
@@ -4783,6 +4817,7 @@ esac
+
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for TTF_Init in -lSDL3_ttf" >&5
printf %s "checking for TTF_Init in -lSDL3_ttf... " >&6; }
if test ${ac_cv_lib_SDL3_ttf_TTF_Init+y}
diff --git a/test/configure.ac b/test/configure.ac
index 8077633c2..9a3490d9c 100644
--- a/test/configure.ac
+++ b/test/configure.ac
@@ -127,6 +127,17 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
]],[])], [have_opengl=yes],[])
AC_MSG_RESULT($have_opengl)
+dnl Check for OpenGL ES
+AC_MSG_CHECKING(for OpenGL ES support)
+have_opengles=no
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #include "SDL_opengles.h"
+ #ifndef SDL_VIDEO_OPENGL_ES
+ #error SDL_VIDEO_OPENGL_ES
+ #endif
+]],[])] ,[have_opengles=yes],[])
+AC_MSG_RESULT($have_opengles)
+
dnl Check for OpenGL ES2
AC_MSG_CHECKING(for OpenGL ES2 support)
have_opengles2=no
@@ -141,8 +152,14 @@ AC_MSG_RESULT($have_opengles2)
GLLIB=""
GLESLIB=""
GLES2LIB=""
+OPENGLES1_TARGETS="UNUSED"
OPENGLES2_TARGETS="UNUSED"
OPENGL_TARGETS="UNUSED"
+if test x$have_opengles = xyes; then
+ CFLAGS="$CFLAGS -DHAVE_OPENGLES"
+ GLESLIB="$XPATH -lGLESv1_CM"
+ OPENGLES1_TARGETS="TARGETS"
+fi
if test x$have_opengles2 = xyes; then
CFLAGS="$CFLAGS -DHAVE_OPENGLES2"
#GLES2LIB="$XPATH -lGLESv2"
@@ -228,6 +245,7 @@ case "$host" in
;;
esac
+AC_SUBST(OPENGLES1_TARGETS)
AC_SUBST(OPENGLES2_TARGETS)
AC_SUBST(OPENGL_TARGETS)
AC_SUBST(GLLIB)
diff --git a/test/testgles.c b/test/testgles.c
new file mode 100644
index 000000000..745cf8919
--- /dev/null
+++ b/test/testgles.c
@@ -0,0 +1,355 @@
+/*
+ Copyright (C) 1997-2022 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely.
+*/
+#include
+#include
+#include
+#include
+
+#include "SDL_test_common.h"
+
+#if defined(__IPHONEOS__) || defined(__ANDROID__)
+#define HAVE_OPENGLES
+#endif
+
+#ifdef HAVE_OPENGLES
+
+#include "SDL_opengles.h"
+
+static SDLTest_CommonState *state;
+static SDL_GLContext *context = NULL;
+static int depth = 16;
+
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void
+quit(int rc)
+{
+ int i;
+
+ if (context != NULL) {
+ for (i = 0; i < state->num_windows; i++) {
+ if (context[i]) {
+ SDL_GL_DeleteContext(context[i]);
+ }
+ }
+
+ SDL_free(context);
+ }
+
+ SDLTest_CommonQuit(state);
+ exit(rc);
+}
+
+static void
+Render()
+{
+ static GLubyte color[8][4] = { {255, 0, 0, 0},
+ {255, 0, 0, 255},
+ {0, 255, 0, 255},
+ {0, 255, 0, 255},
+ {0, 255, 0, 255},
+ {255, 255, 255, 255},
+ {255, 0, 255, 255},
+ {0, 0, 255, 255}
+ };
+ static GLfloat cube[8][3] = { {0.5, 0.5, -0.5},
+ {0.5f, -0.5f, -0.5f},
+ {-0.5f, -0.5f, -0.5f},
+ {-0.5f, 0.5f, -0.5f},
+ {-0.5f, 0.5f, 0.5f},
+ {0.5f, 0.5f, 0.5f},
+ {0.5f, -0.5f, 0.5f},
+ {-0.5f, -0.5f, 0.5f}
+ };
+ static GLubyte indices[36] = { 0, 3, 4,
+ 4, 5, 0,
+ 0, 5, 6,
+ 6, 1, 0,
+ 6, 7, 2,
+ 2, 1, 6,
+ 7, 4, 3,
+ 3, 2, 7,
+ 5, 4, 7,
+ 7, 6, 5,
+ 2, 3, 1,
+ 3, 0, 1
+ };
+
+
+ /* Do our drawing, too. */
+ glClearColor(0.0, 0.0, 0.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ /* Draw the cube */
+ glColorPointer(4, GL_UNSIGNED_BYTE, 0, color);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 0, cube);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, indices);
+
+ glMatrixMode(GL_MODELVIEW);
+ glRotatef(5.0, 1.0, 1.0, 1.0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int fsaa, accel;
+ int value;
+ int i, done;
+ SDL_DisplayMode mode;
+ SDL_Event event;
+ Uint32 then, now, frames;
+ int status;
+
+ /* Enable standard application logging */
+ SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
+
+ /* Initialize parameters */
+ fsaa = 0;
+ accel = 0;
+
+ /* Initialize test framework */
+ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
+ if (!state) {
+ return 1;
+ }
+ for (i = 1; i < argc;) {
+ int consumed;
+
+ consumed = SDLTest_CommonArg(state, i);
+ if (consumed == 0) {
+ if (SDL_strcasecmp(argv[i], "--fsaa") == 0) {
+ ++fsaa;
+ consumed = 1;
+ } else if (SDL_strcasecmp(argv[i], "--accel") == 0) {
+ ++accel;
+ consumed = 1;
+ } else if (SDL_strcasecmp(argv[i], "--zdepth") == 0) {
+ i++;
+ if (!argv[i]) {
+ consumed = -1;
+ } else {
+ depth = SDL_atoi(argv[i]);
+ consumed = 1;
+ }
+ } else {
+ consumed = -1;
+ }
+ }
+ if (consumed < 0) {
+ static const char *options[] = { "[--fsaa]", "[--accel]", "[--zdepth %d]", NULL };
+ SDLTest_CommonLogUsage(state, argv[0], options);
+ quit(1);
+ }
+ i += consumed;
+ }
+
+ /* Set OpenGL parameters */
+ state->window_flags |= SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_BORDERLESS;
+ state->gl_red_size = 5;
+ state->gl_green_size = 5;
+ state->gl_blue_size = 5;
+ state->gl_depth_size = depth;
+ state->gl_major_version = 1;
+ state->gl_minor_version = 1;
+ state->gl_profile_mask = SDL_GL_CONTEXT_PROFILE_ES;
+ if (fsaa) {
+ state->gl_multisamplebuffers=1;
+ state->gl_multisamplesamples=fsaa;
+ }
+ if (accel) {
+ state->gl_accelerated=1;
+ }
+ if (!SDLTest_CommonInit(state)) {
+ quit(2);
+ }
+
+ context = (SDL_GLContext *)SDL_calloc(state->num_windows, sizeof(*context));
+ if (context == NULL) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n");
+ quit(2);
+ }
+
+ /* Create OpenGL ES contexts */
+ for (i = 0; i < state->num_windows; i++) {
+ context[i] = SDL_GL_CreateContext(state->windows[i]);
+ if (!context[i]) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_GL_CreateContext(): %s\n", SDL_GetError());
+ quit(2);
+ }
+ }
+
+ if (state->render_flags & SDL_RENDERER_PRESENTVSYNC) {
+ SDL_GL_SetSwapInterval(1);
+ } else {
+ SDL_GL_SetSwapInterval(0);
+ }
+
+ SDL_GetCurrentDisplayMode(0, &mode);
+ SDL_Log("Screen bpp: %d\n", SDL_BITSPERPIXEL(mode.format));
+ SDL_Log("\n");
+ SDL_Log("Vendor : %s\n", glGetString(GL_VENDOR));
+ SDL_Log("Renderer : %s\n", glGetString(GL_RENDERER));
+ SDL_Log("Version : %s\n", glGetString(GL_VERSION));
+ SDL_Log("Extensions : %s\n", glGetString(GL_EXTENSIONS));
+ SDL_Log("\n");
+
+ status = SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &value);
+ if (!status) {
+ SDL_Log("SDL_GL_RED_SIZE: requested %d, got %d\n", 5, value);
+ } else {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_RED_SIZE: %s\n",
+ SDL_GetError());
+ }
+ status = SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &value);
+ if (!status) {
+ SDL_Log("SDL_GL_GREEN_SIZE: requested %d, got %d\n", 5, value);
+ } else {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_GREEN_SIZE: %s\n",
+ SDL_GetError());
+ }
+ status = SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &value);
+ if (!status) {
+ SDL_Log("SDL_GL_BLUE_SIZE: requested %d, got %d\n", 5, value);
+ } else {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_BLUE_SIZE: %s\n",
+ SDL_GetError());
+ }
+ status = SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &value);
+ if (!status) {
+ SDL_Log("SDL_GL_DEPTH_SIZE: requested %d, got %d\n", depth, value);
+ } else {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_DEPTH_SIZE: %s\n",
+ SDL_GetError());
+ }
+ if (fsaa) {
+ status = SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &value);
+ if (!status) {
+ SDL_Log("SDL_GL_MULTISAMPLEBUFFERS: requested 1, got %d\n", value);
+ } else {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_MULTISAMPLEBUFFERS: %s\n",
+ SDL_GetError());
+ }
+ status = SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &value);
+ if (!status) {
+ SDL_Log("SDL_GL_MULTISAMPLESAMPLES: requested %d, got %d\n", fsaa,
+ value);
+ } else {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_MULTISAMPLESAMPLES: %s\n",
+ SDL_GetError());
+ }
+ }
+ if (accel) {
+ status = SDL_GL_GetAttribute(SDL_GL_ACCELERATED_VISUAL, &value);
+ if (!status) {
+ SDL_Log("SDL_GL_ACCELERATED_VISUAL: requested 1, got %d\n", value);
+ } else {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get SDL_GL_ACCELERATED_VISUAL: %s\n",
+ SDL_GetError());
+ }
+ }
+
+ /* Set rendering settings for each context */
+ for (i = 0; i < state->num_windows; ++i) {
+ float aspectAdjust;
+
+ status = SDL_GL_MakeCurrent(state->windows[i], context[i]);
+ if (status) {
+ SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError());
+
+ /* Continue for next window */
+ continue;
+ }
+
+ aspectAdjust = (4.0f / 3.0f) / ((float)state->window_w / state->window_h);
+ glViewport(0, 0, state->window_w, state->window_h);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrthof(-2.0, 2.0, -2.0 * aspectAdjust, 2.0 * aspectAdjust, -20.0, 20.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+ glShadeModel(GL_SMOOTH);
+ }
+
+ /* Main render loop */
+ frames = 0;
+ then = SDL_GetTicks();
+ done = 0;
+ while (!done) {
+ /* Check for events */
+ ++frames;
+ while (SDL_PollEvent(&event)) {
+ switch (event.type) {
+ case SDL_WINDOWEVENT:
+ switch (event.window.event) {
+ case SDL_WINDOWEVENT_RESIZED:
+ for (i = 0; i < state->num_windows; ++i) {
+ if (event.window.windowID == SDL_GetWindowID(state->windows[i])) {
+ status = SDL_GL_MakeCurrent(state->windows[i], context[i]);
+ if (status) {
+ SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError());
+ break;
+ }
+ /* Change view port to the new window dimensions */
+ glViewport(0, 0, event.window.data1, event.window.data2);
+ /* Update window content */
+ Render();
+ SDL_GL_SwapWindow(state->windows[i]);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ SDLTest_CommonEvent(state, &event, &done);
+ }
+ for (i = 0; i < state->num_windows; ++i) {
+ if (state->windows[i] == NULL)
+ continue;
+ status = SDL_GL_MakeCurrent(state->windows[i], context[i]);
+ if (status) {
+ SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError());
+
+ /* Continue for next window */
+ continue;
+ }
+ Render();
+ SDL_GL_SwapWindow(state->windows[i]);
+ }
+ }
+
+ /* Print out some timing information */
+ now = SDL_GetTicks();
+ if (now > then) {
+ SDL_Log("%2.2f frames per second\n",
+ ((double) frames * 1000) / (now - then));
+ }
+#if !defined(__ANDROID__)
+ quit(0);
+#endif
+ return 0;
+}
+
+#else /* HAVE_OPENGLES */
+
+int
+main(int argc, char *argv[])
+{
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "No OpenGL ES support on this system\n");
+ return 1;
+}
+
+#endif /* HAVE_OPENGLES */
+
+/* vi: set ts=4 sw=4 expandtab: */