-/* xscreensaver, Copyright (c) 2012-2016 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright © 2012-2023 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* implied warranty.
*/
-/* A compatibility shim to allow OpenGL 1.3 source code to work in an
- OpenGLES environment, where almost every OpenGL 1.3 function has
- been "deprecated".
+/* JWXYZ Is Not Xlib.
+
+ See the comment at the top of jwxyz-common.c for an explanation of
+ the division of labor between these various modules.
+
+ This file is a compatibility shim to allow OpenGL 1.3 source code to
+ work in an OpenGLES environment, where almost every OpenGL 1.3 function
+ has been "deprecated".
There are two major operations going on here:
OpenGLES 1.0 2003 (deprecated 80% of the language; fork of OpenGL 1.3)
OpenGL 1.5 2003 (added VBOs)
OpenGLES 1.1 2004 (fork of OpenGL 1.5)
- OpenGL 2.0 2004 (a political quagmire)
- OpenGLES 2.0 2007 (deprecated 95% of the language; fork of OpenGL 2.0)
+ OpenGL 2.0 2004 (a political quagmire, added shader language GLSL 1.1)
+ OpenGLES 2.0 2007 (deprecated 95% of the language; fork of OpenGL 2.0;
+ GLSL 1.20)
OpenGL 3.0 2008 (added FBOs, VAOs, deprecated 60% of the language)
+ OpenGL 3.3 2010 (OpenGL 3.3 and OpenGL 4.0 released concurrently;
+ 3.3 has GLSL 3.30, but 4.0 has GLSL 4.00)
+ OpenGLES 3.0 2012 (same as WebGL 2.0, but has GLSL 3.00)
+ OpenGL 4.3 2012 (superset of GLES 3.0, but has GLSL 4.30)
+
+ It's like these assholes are going out of their way to make it all just
+ as incoherent and difficult to understand as possible.
Some things that are missing:
#ifdef HAVE_JWZGLES /* whole file */
+#ifndef HAVE_GL
+# error HAVE_GL is undefined
+#endif
+
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
-#if defined(USE_IPHONE)
-# include <OpenGLES/ES1/gl.h>
-# include <OpenGLES/ES1/glext.h>
+#if defined(HAVE_IPHONE)
+# ifdef HAVE_GLES3
+# include <OpenGLES/ES3/gl.h>
+# include <OpenGLES/ES3/glext.h>
+# else /* !HAVE_GLES3 */
+# include <OpenGLES/ES1/gl.h>
+# include <OpenGLES/ES1/glext.h>
+# endif /* !HAVE_GLES3 */
#elif defined(HAVE_COCOA)
# include <OpenGL/gl.h>
-# include <OpenGL/glu.h>
#elif defined(HAVE_ANDROID)
# include <GLES/gl.h>
+# ifdef HAVE_GLES3
+# include <GLES3/gl3.h>
+# endif
# include <android/log.h>
#else /* real X11 */
# ifndef GL_GLEXT_PROTOTYPES
# define GL_GLEXT_PROTOTYPES /* for glBindBuffer */
# endif
-# include <GL/glx.h>
-# include <GL/glu.h>
+# include <GLES/gl.h>
+# ifdef HAVE_GLES3
+# include <GLES3/gl3.h>
+# endif /* HAVE_GLES3 */
#endif
#include "jwzglesI.h"
#ifdef DEBUG
-static void Log(const char *fmt, ...)
+void
+Log(const char *fmt, ...)
{
va_list args;
va_start (args, fmt);
jwzgles_glColor4i (GLint r, GLint g, GLint b, GLint a)
{
/* -0x8000000 - 0x7FFFFFFF => 0.0 - 1.0 */
- jwzgles_glColor4f (0.5 + (GLfloat) r / 0xFFFFFFFF,
- 0.5 + (GLfloat) g / 0xFFFFFFFF,
- 0.5 + (GLfloat) b / 0xFFFFFFFF,
- 0.5 + (GLfloat) a / 0xFFFFFFFF);
+ jwzgles_glColor4f (0.5 + (double) r / 0xFFFFFFFF, /* Not GLfloat */
+ 0.5 + (double) g / 0xFFFFFFFF,
+ 0.5 + (double) b / 0xFFFFFFFF,
+ 0.5 + (double) a / 0xFFFFFFFF);
}
void
jwzgles_glColor4ui (GLuint r, GLuint g, GLuint b, GLuint a)
{
/* 0 - 0xFFFFFFFF => 0.0 - 1.0 */
- jwzgles_glColor4f ((GLfloat) r / 0xFFFFFFFF,
- (GLfloat) g / 0xFFFFFFFF,
- (GLfloat) b / 0xFFFFFFFF,
- (GLfloat) a / 0xFFFFFFFF);
+ jwzgles_glColor4f ((double) r / 0xFFFFFFFF, /* Not GLfloat */
+ (double) g / 0xFFFFFFFF,
+ (double) b / 0xFFFFFFFF,
+ (double) a / 0xFFFFFFFF);
}
void
jwzgles_glColor4s (GLshort r, GLshort g, GLshort b, GLshort a)
{
/* -0x8000 - 0x7FFF => 0.0 - 1.0 */
- jwzgles_glColor4f (0.5 + (GLfloat) r / 0xFFFF,
- 0.5 + (GLfloat) g / 0xFFFF,
- 0.5 + (GLfloat) b / 0xFFFF,
- 0.5 + (GLfloat) a / 0xFFFF);
+ jwzgles_glColor4f (0.5 + (double) r / 0xFFFF, /* Not GLfloat */
+ 0.5 + (double) g / 0xFFFF,
+ 0.5 + (double) b / 0xFFFF,
+ 0.5 + (double) a / 0xFFFF);
}
void
jwzgles_glColor4b (GLbyte r, GLbyte g, GLbyte b, GLbyte a)
{
/* -128 - 127 => 0.0 - 1.0 */
- jwzgles_glColor4f (0.5 + (GLfloat) r / 255,
- 0.5 + (GLfloat) g / 255,
- 0.5 + (GLfloat) b / 255,
- 0.5 + (GLfloat) a / 255);
+ jwzgles_glColor4f (0.5 + (double) r / 255, /* Not GLfloat */
+ 0.5 + (double) g / 255,
+ 0.5 + (double) b / 255,
+ 0.5 + (double) a / 255);
}
void
}
else
{
-/* Assert (buf == GL_BACK, "glDrawBuffer: back buffer only"); */
-# ifndef GL_VERSION_ES_CM_1_0 /* not compiling against OpenGLES 1.x */
+ Assert (buf == GL_BACK, "glDrawBuffer: back buffer only");
+# if !defined(GL_VERSION_ES_CM_1_0)
+ /* not compiling against OpenGLES 1.x */
if (! state->replaying_list)
LOG1 ("direct %-12s", "glDrawBuffer");
glDrawBuffer (buf); /* the real one */
}
+void jwzgles_glDrawElements (GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ Assert (!state->compiling_verts, "not allowed inside glBegin");
+ Assert (!state->compiling_list, "not allowed inside glNewList");
+# if 0
+ if (state->compiling_list)
+ {
+ void_int vv[1];
+ vv[0].i = buf;
+ /* #### This won't work because indices is a pointer */
+ list_push ("glDrawElements", (list_fn_cb) &jwzgles_glDrawElements,
+ PROTO_IIII, vv);
+ }
+ else
+# endif /* 0 */
+ {
+ glDrawElements (mode, count, type, indices); /* the real one */
+ CHECK("glDrawElements");
+ }
+}
+
+
/* Given an array of sets of 4 elements of arbitrary size, convert it
to an array of sets of 6 elements instead: ABCD becomes ABC BCD.
*/
jwzgles_glDrawArrays (s->mode, 0, s->count);
glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */
-# define RESET(VAR,FN,ARG) do { \
+# define RESET(VAR,ENFN,DISFN,ARG) do { \
if (is_##VAR != was_##VAR) { \
- if (was_##VAR) jwzgles_glEnable##FN (ARG); \
- else jwzgles_glDisable##FN (ARG); \
+ if (was_##VAR) jwzgles_gl##ENFN (ARG); \
+ else jwzgles_gl##DISFN (ARG); \
}} while(0)
- RESET (norm, ClientState, GL_NORMAL_ARRAY);
- RESET (tex, ClientState, GL_TEXTURE_COORD_ARRAY);
- RESET (color, ClientState, GL_COLOR_ARRAY);
- RESET (mat, , GL_COLOR_MATERIAL);
+ RESET (norm, EnableClientState, DisableClientState, GL_NORMAL_ARRAY);
+ RESET (tex, EnableClientState, DisableClientState, GL_TEXTURE_COORD_ARRAY);
+ RESET (color, EnableClientState, DisableClientState, GL_COLOR_ARRAY);
+ RESET (mat, Enable, Disable, GL_COLOR_MATERIAL);
# undef RESET
s->count = 0;
Assert (!state->compiling_verts, "glTexImage1D not allowed inside glBegin");
/* technically legal, but stupid! */
Assert (!state->compiling_list, "glTexImage1D inside glNewList");
+# ifndef HAVE_GLSL
+ /* If the underlying library is GLES2, then textures can be any size.
+ Portable code should still be using pow2 sizes, unless it's in a branch
+ that is guaranteed not to run in a GLES1 or OpenGL 1.3 context. */
Assert (width == to_pow2(width), "width must be a power of 2");
+# endif
if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
jwzgles_glTexImage2D (target, level, internalFormat, width, 1,
Assert (!state->compiling_list, /* technically legal, but stupid! */
"glTexImage2D not allowed inside glNewList");
+# ifndef HAVE_GLSL
+ /* If the underlying library is GLES2, then textures can be any size.
+ Portable code should still be using pow2 sizes, unless it's in a branch
+ that is guaranteed not to run in a GLES1 or OpenGL 1.3 context. */
Assert (width == to_pow2(width), "width must be a power of 2");
Assert (height == to_pow2(height), "height must be a power of 2");
+# endif
/* OpenGLES no longer supports "4" as a synonym for "RGBA". */
switch (internalFormat) {
}
+void
+jwzgles_glCopyTexSubImage2D (GLenum target, GLint level,
+ GLint xoff, GLint yoff,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height)
+{
+ Assert (!state->compiling_verts,
+ "glCopyTexSubImage2D not allowed inside glBegin");
+ Assert (!state->compiling_list, /* technically legal, but stupid! */
+ "glCopyTexSubImage2D not allowed inside glNewList");
+ if (! state->replaying_list)
+ LOG9 ("direct %-12s %s %d %d %d %d %d %d %d", "glCopyTexSubImage2D",
+ mode_desc(target), level, xoff, yoff, x, y, width, height);
+ glCopyTexSubImage2D (target, level, /* the real one */
+ xoff, yoff, x, y, width, height);
+ CHECK("glCopyTexSubImage2D");
+}
+
+
/* OpenGLES doesn't have auto texture-generation at all!
"Oh, just rewrite that code to use GPU shaders", they say.
How fucking convenient.
size_t ext_len = strlen ((const char *)ext_name);
for (;;) {
+ char last_ch;
const GLubyte *found = (const GLubyte *)strstr ((const char *)ext_string,
(const char *)ext_name);
if (!found)
break;
- char last_ch = found[ext_len];
+ last_ch = found[ext_len];
if ((found == ext_string || found[-1] == ' ') &&
(last_ch == ' ' || !last_ch)) {
return GL_TRUE;
WRAP (glActiveTexture, I)
WRAP (glAlphaFunc, IF)
WRAP (glBlendFunc, II)
+WRAP (glBlendColor, FFFF)
+WRAP (glBlendEquation, I)
WRAP (glClear, I)
WRAP (glClearColor, FFFF)
WRAP (glClearStencil, I)
#define TYPE_IV GLuint
WRAP (glDeleteTextures, IIV)
-
#endif /* HAVE_JWZGLES - whole file */