summaryrefslogtreecommitdiffstats
path: root/jwxyz
diff options
context:
space:
mode:
Diffstat (limited to 'jwxyz')
-rw-r--r--jwxyz/Makefile.in30
-rw-r--r--jwxyz/jwxyz-android.c300
-rw-r--r--jwxyz/jwxyz-cocoa.h16
-rw-r--r--jwxyz/jwxyz-cocoa.m69
-rw-r--r--jwxyz/jwxyz-common.c48
-rw-r--r--jwxyz/jwxyz-gl.c21
-rw-r--r--jwxyz/jwxyz-image.c10
-rw-r--r--jwxyz/jwxyz.h18
-rw-r--r--jwxyz/jwxyz.m42
-rw-r--r--jwxyz/jwxyzI.h5
-rw-r--r--jwxyz/jwzgles.c108
-rw-r--r--jwxyz/jwzgles.h2
-rw-r--r--jwxyz/jwzglesI.h4
13 files changed, 484 insertions, 189 deletions
diff --git a/jwxyz/Makefile.in b/jwxyz/Makefile.in
index 0ba48a6..1f6d6ae 100644
--- a/jwxyz/Makefile.in
+++ b/jwxyz/Makefile.in
@@ -1,4 +1,4 @@
-# utils/Makefile.in --- xscreensaver, Copyright (c) 1997-2010 Jamie Zawinski.
+# utils/Makefile.in --- xscreensaver, Copyright © 1997-2021 Jamie Zawinski.
# the `../configure' script generates `jwxyz/Makefile' from this file.
# JWXYZ Is Not Xlib.
@@ -97,8 +97,8 @@ TAGS: tags
tags:
find $(srcdir) -name '*.[chly]' -print | xargs etags -a
-echo_tarfiles:
- @echo $(TARFILES)
+list_tarfiles:
+ @find $(TARFILES) -type f -print | sort
# How we build object files in this directory.
@@ -106,30 +106,6 @@ echo_tarfiles:
$(CC) -c $(INCLUDES) $(DEFS) $(CPPFLAGS) $(CFLAGS) $(X_CFLAGS) $<
-# Rules for generating the VMS makefiles on Unix, so that it doesn't have to
-# be done by hand...
-#
-VMS_AXP_COMPILE=$$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-])
-
-compile_axp.com: Makefile.in
- @echo generating $@ from $<... ; \
- ( ( for c in $(SRCS) vms-*.c ; do \
- c=`echo $$c | tr a-z A-Z` ; \
- echo "$(VMS_AXP_COMPILE) $$c" ; \
- done ; \
- ) | sort -d ; \
- echo '$$ lib/cre utils.olb_axp' ; \
- echo '$$ lib utils.olb_axp *.obj' ; \
- echo '$$! delete/noconf *.obj;' ; \
- ) > $@
-
-compile_decc.com: compile_axp.com
- @echo generating $@ from $<... ; \
- sed 's/axp/decc/g' < $< > $@
-
-distdepend:: compile_axp.com compile_decc.com
-
-
##############################################################################
#
# DO NOT DELETE: updated by make distdepend
diff --git a/jwxyz/jwxyz-android.c b/jwxyz/jwxyz-android.c
index 85ce924..c84028b 100644
--- a/jwxyz/jwxyz-android.c
+++ b/jwxyz/jwxyz-android.c
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2016-2018 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright © 2016-2021 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
@@ -7,13 +7,19 @@
* documentation. No representations are made about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
- *
- * This file is three related things:
- *
- * - It is the Android-specific C companion to jwxyz-gl.c;
- * - It is how C calls into Java to do things that OpenGL does not
- * have access to without Java-based APIs;
- * - It is how the jwxyz.java class calls into C to run the hacks.
+ */
+
+/* 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 three related things:
+
+ - It is the Android-specific companion to jwxyz-gl.c or jwxyz-image.c;
+ - It is how C calls into Java to do things that OpenGL does not have
+ access to without Java-based APIs;
+ - It is how the jwxyz.java class calls into C to run the hacks.
*/
#ifdef HAVE_ANDROID /* whole file */
@@ -25,8 +31,13 @@
#include <math.h>
#include <setjmp.h>
+#define GL_GLEXT_PROTOTYPES
+
#include <GLES/gl.h>
#include <GLES/glext.h>
+#ifdef HAVE_GLES3
+# include <GLES3/gl3.h>
+#endif
#include <jni.h>
#include <android/bitmap.h>
#include <android/log.h>
@@ -228,6 +239,202 @@ prepare_context (struct running_hack *rh)
}
+static void
+get_egl_config_android(Window window, EGLDisplay *egl_display,
+ EGLConfig *egl_config)
+{
+# define R EGL_RED_SIZE
+# define G EGL_GREEN_SIZE
+# define B EGL_BLUE_SIZE
+# define A EGL_ALPHA_SIZE
+# define D EGL_DEPTH_SIZE
+# define I EGL_BUFFER_SIZE
+# define ST EGL_STENCIL_SIZE
+ EGLint templates[][40] = {
+ { R,8, G,8, B,8, A,8, D,8, ST,1, EGL_NONE }, /* rgba stencil */
+ { R,8, G,8, B,8, D,8, ST,1, EGL_NONE }, /* rgb stencil */
+ { R,4, G,4, B,4, D,4, ST,1, EGL_NONE },
+ { R,2, G,2, B,2, D,2, ST,1, EGL_NONE },
+ { R,8, G,8, B,8, A,8, D,8, EGL_NONE }, /* rgba */
+ { R,8, G,8, B,8, D,8, EGL_NONE }, /* rgb */
+ { R,4, G,4, B,4, D,4, EGL_NONE },
+ { R,2, G,2, B,2, D,2, EGL_NONE },
+ { R,1, G,1, B,1, D,1, EGL_NONE } /* monochrome */
+ };
+ EGLint attrs[40];
+ EGLint nconfig;
+ int i, j, k, iter, pass;
+
+ char *glsls = get_string_resource_window (window, "prefersGLSL");
+ Bool glslp = (glsls && !strcasecmp(glsls, "true"));
+ iter = (glslp ? 2 : 1);
+
+ *egl_config = 0;
+ for (pass = 0; pass < iter; pass++)
+ {
+ for (i = 0; i < countof(templates); i++)
+ {
+ for (j = 0, k = 0; templates[i][j] != EGL_NONE; j += 2)
+ {
+ attrs[k++] = templates[i][j];
+ attrs[k++] = templates[i][j+1];
+ }
+
+ attrs[k++] = EGL_RENDERABLE_TYPE;
+# ifdef HAVE_GLES3
+ if (glslp && pass == 0)
+ attrs[k++] = EGL_OPENGL_ES3_BIT;
+ else
+ attrs[k++] = EGL_OPENGL_ES_BIT;
+# else
+ attrs[k++] = EGL_OPENGL_ES_BIT;
+# endif
+
+ attrs[k++] = EGL_NONE;
+
+ nconfig = -1;
+ if (eglChooseConfig (egl_display, attrs, egl_config, 1, &nconfig)
+ && nconfig == 1)
+ break;
+ }
+ if (i < countof(templates))
+ break;
+ }
+ Assert (*egl_config != 0, "no EGL config chosen");
+#if 1
+ {
+ int i;
+ const struct { int hexp; EGLint i; const char *s; } fields[] = {
+ { 1, EGL_CONFIG_ID, "config ID:" },
+ { 1, EGL_CONFIG_CAVEAT, "caveat:" },
+ { 1, EGL_CONFORMANT, "conformant:" },
+ { 0, EGL_COLOR_BUFFER_TYPE, "buffer type:" },
+ { 0, EGL_RED_SIZE, "color size:" },
+ { 0, EGL_TRANSPARENT_RED_VALUE, "transparency:" },
+ { 0, EGL_BUFFER_SIZE, "buffer size:" },
+ { 0, EGL_DEPTH_SIZE, "depth size:" },
+ { 0, EGL_LUMINANCE_SIZE, "lum size:" },
+ { 0, EGL_STENCIL_SIZE, "stencil size:" },
+ { 0, EGL_ALPHA_MASK_SIZE, "alpha mask:" },
+ { 0, EGL_LEVEL, "level:" },
+ { 0, EGL_SAMPLES, "samples:" },
+ { 0, EGL_SAMPLE_BUFFERS, "sample bufs:" },
+ { 0, EGL_NATIVE_RENDERABLE, "native render:" },
+ { 1, EGL_NATIVE_VISUAL_TYPE, "native type:" },
+ { 1, EGL_RENDERABLE_TYPE, "render type:" },
+ { 0, EGL_SURFACE_TYPE, "surface type:" },
+ { 0, EGL_BIND_TO_TEXTURE_RGB, "bind RGB:" },
+ { 0, EGL_BIND_TO_TEXTURE_RGBA, "bind RGBA:" },
+ { 0, EGL_MAX_PBUFFER_WIDTH, "buffer width:" },
+ { 0, EGL_MAX_PBUFFER_HEIGHT, "buffer height:" },
+ { 0, EGL_MAX_PBUFFER_PIXELS, "buffer pixels:" },
+ { 0, EGL_MAX_SWAP_INTERVAL, "max swap:" },
+ { 0, EGL_MIN_SWAP_INTERVAL, "min swap:" },
+ };
+ EGLint r=0, g=0, b=0, a=0, tt=0, tr=0, tg=0, tb=0;
+ eglGetConfigAttrib (egl_display, *egl_config, EGL_RED_SIZE, &r);
+ eglGetConfigAttrib (egl_display, *egl_config, EGL_GREEN_SIZE, &g);
+ eglGetConfigAttrib (egl_display, *egl_config, EGL_BLUE_SIZE, &b);
+ eglGetConfigAttrib (egl_display, *egl_config, EGL_ALPHA_SIZE, &a);
+ eglGetConfigAttrib (egl_display, *egl_config,
+ EGL_TRANSPARENT_TYPE, &tt);
+ eglGetConfigAttrib (egl_display, *egl_config,
+ EGL_TRANSPARENT_RED_VALUE, &tr);
+ eglGetConfigAttrib (egl_display, *egl_config,
+ EGL_TRANSPARENT_GREEN_VALUE,&tg);
+ eglGetConfigAttrib (egl_display, *egl_config,
+ EGL_TRANSPARENT_BLUE_VALUE, &tb);
+ for (i = 0; i < countof(fields); i++)
+ {
+ EGLint v = 0;
+ char s[100];
+ eglGetConfigAttrib (egl_display, *egl_config, fields[i].i, &v);
+ if (fields[i].i == EGL_RED_SIZE)
+ sprintf (s, "%d, %d, %d, %d", r, g, b, a);
+ else if (fields[i].i == EGL_TRANSPARENT_RED_VALUE && tt != EGL_NONE)
+ sprintf (s, "%d, %d, %d", tr, tg, tb);
+ else if (fields[i].i == EGL_CONFIG_CAVEAT)
+ strcpy (s, (v == EGL_NONE ? "none" :
+ v == EGL_SLOW_CONFIG ? "slow" :
+# ifdef EGL_NON_CONFORMANT
+ v == EGL_NON_CONFORMANT ? "non-conformant" :
+# endif
+ "???"));
+ else if (fields[i].i == EGL_COLOR_BUFFER_TYPE)
+ strcpy (s, (v == EGL_RGB_BUFFER ? "RGB" :
+ v == EGL_LUMINANCE_BUFFER ? "luminance" :
+ "???"));
+ else if (fields[i].i == EGL_CONFORMANT ||
+ fields[i].i == EGL_RENDERABLE_TYPE)
+ {
+ sprintf (s, "0x%02x", v);
+ if (v & EGL_OPENGL_BIT) strcat (s, " OpenGL");
+ if (v & EGL_OPENGL_ES_BIT) strcat (s, " GLES-1.x");
+ if (v & EGL_OPENGL_ES2_BIT) strcat (s, " GLES-2.0");
+# ifdef EGL_OPENGL_ES3_BIT
+ if (v & EGL_OPENGL_ES3_BIT) strcat (s, " GLES-3.0");
+# endif
+ if (v & EGL_OPENVG_BIT) strcat (s, " OpenVG");
+ }
+ else if (fields[i].hexp)
+ sprintf (s, "0x%02x", v);
+ else if (v)
+ sprintf (s, "%d", v);
+ else
+ *s = 0;
+
+ if (*s) Log ("init: EGL %-14s %s\n", fields[i].s, s);
+ }
+ }
+#endif
+}
+
+
+static void
+get_egl_context_android(Window window, EGLDisplay *egl_display,
+ EGLConfig *egl_config, EGLContext *egl_context)
+{
+ EGLint context_attribs[][3] = {
+ { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE },
+ { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE }
+ };
+ EGLint *attrs;
+ Bool glslp;
+ int pass, iter;
+
+# ifdef EGL_OPENGL_ES3_BIT
+ char *glsls = get_string_resource_window (window, "prefersGLSL");
+ glslp = (glsls && !strcasecmp(glsls, "true"));
+ if (glslp)
+ {
+ EGLint renderable_type;
+ eglGetConfigAttrib (egl_display, egl_config, EGL_RENDERABLE_TYPE,
+ &renderable_type);
+ Bool gles3p = (renderable_type & EGL_OPENGL_ES3_BIT) != 0;
+ glslp = glslp && gles3p;
+ }
+# else
+ glslp = False;
+# endif
+ iter = (glslp ? 2 : 1);
+
+ *egl_context = EGL_NO_CONTEXT;
+ for (pass = 0; pass < iter; pass++)
+ {
+ if (glslp && pass == 0)
+ attrs = context_attribs[1];
+ else
+ attrs = context_attribs[0];
+ *egl_context = eglCreateContext (egl_display, egl_config,
+ EGL_NO_CONTEXT, attrs);
+ if (*egl_context != EGL_NO_CONTEXT)
+ break;
+ }
+
+ Assert (*egl_context != EGL_NO_CONTEXT, "init: EGL_NO_CONTEXT");
+}
+
+
// Initialized OpenGL and runs the screenhack's init function.
//
static void
@@ -344,7 +551,24 @@ doinit (jobject jwxyz_obj, struct running_hack *rh, JNIEnv *env,
/* Note: https://source.android.com/devices/graphics/arch-egl-opengl */
- /* ####: This is lame, use a resource. */
+ /* jwxyz_gl_p controls which implementation of Pixmaps we are using.
+
+ - jwxyz-image.c implements them in CPU RAM, and is used for Android GL
+ hacks, and for kumppa, petri and slip, which are too slow otherwise.
+
+ - jwxyz-gl.c implements them in terms of OpenGL textures, and is used
+ for all other Android X11 hacks.
+
+ Why two implemementations of Pixmaps for Android?
+
+ - GL hacks don't tend to need much in the way of Xlib, and having a
+ GL context to render Xlib alongside a GL context for rendering GL
+ seemed like trouble.
+
+ - X11 hacks render to a GL context because hardware acceleration tends
+ to work well with Xlib geometric stuff. Better framerates, lower
+ power.
+ */
rh->jwxyz_gl_p =
rh->xsft->visual == DEFAULT_VISUAL &&
strcmp (progname, "kumppa") &&
@@ -357,48 +581,27 @@ doinit (jobject jwxyz_obj, struct running_hack *rh, JNIEnv *env,
rh->egl_p = rh->jwxyz_gl_p || rh->xsft->visual == GL_VISUAL;
+ int egl_major = -1, egl_minor = -1;
+
if (rh->egl_p) {
// GL init. Must come after resource processing.
rh->egl_display = eglGetDisplay (EGL_DEFAULT_DISPLAY);
Assert (rh->egl_display != EGL_NO_DISPLAY, "init: EGL_NO_DISPLAY");
- int egl_major, egl_minor;
Assert (eglInitialize (rh->egl_display, &egl_major, &egl_minor),
"eglInitialize failed");
- // TODO: Skip depth and (probably) alpha for Xlib.
- // TODO: Could ask for EGL_SWAP_BEHAVIOR_PRESERVED_BIT here...maybe?
- // TODO: Probably should try to ask for EGL_PBUFFER_BIT.
- // TODO: Do like visual-gl.c and work from a list of configs.
- /* Probably don't need EGL_FRAMEBUFFER_TARGET_ANDROID here if GLSurfaceView
- doesn't use it.
- */
- EGLint config_attribs[] = {
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, 8,
- EGL_DEPTH_SIZE, 16,
- EGL_NONE
- };
-
- EGLint num_config;
- Assert (eglChooseConfig (rh->egl_display, config_attribs,
- &rh->egl_config, 1, &num_config),
- "eglChooseConfig failed");
- Assert (num_config == 1, "no EGL config chosen");
+ get_egl_config_android (rh->window, rh->egl_display, &rh->egl_config);
- EGLint no_attribs[] = {EGL_NONE};
- rh->egl_ctx = eglCreateContext (rh->egl_display, rh->egl_config,
- EGL_NO_CONTEXT, no_attribs);
- Assert (rh->egl_ctx != EGL_NO_CONTEXT, "init: EGL_NO_CONTEXT");
+ get_egl_context_android(rh->window, rh->egl_display, rh->egl_config,
+ &rh->egl_ctx);
ANativeWindow *native_window =
ANativeWindow_fromSurface (env, jni_surface);
rh->egl_surface = eglCreateWindowSurface (rh->egl_display, rh->egl_config,
- native_window, no_attribs);
+ native_window, NULL);
Assert (rh->egl_surface != EGL_NO_SURFACE, "init: EGL_NO_SURFACE");
ANativeWindow_release (native_window);
@@ -423,10 +626,12 @@ doinit (jobject jwxyz_obj, struct running_hack *rh, JNIEnv *env,
prepare_context (rh);
if (rh->egl_p) {
- Log ("init %s / %s / %s",
+ // GL_SHADING_LANGUAGE_VERSION undefined
+ Log ("init %s / %s / %s / EGL %d.%d",
glGetString (GL_VENDOR),
glGetString (GL_RENDERER),
- glGetString (GL_VERSION));
+ glGetString (GL_VERSION),
+ egl_major, egl_minor);
}
if (rh->jwxyz_gl_p) {
@@ -487,10 +692,7 @@ doinit (jobject jwxyz_obj, struct running_hack *rh, JNIEnv *env,
} else {
- if (rh->xsft->visual == DEFAULT_VISUAL)
- create_pixmap (wnd, wnd);
- else
- wnd->image_data = NULL;
+ create_pixmap (wnd, wnd);
static const unsigned char rgba_bytes[] = {0, 1, 2, 3};
rh->dpy = jwxyz_image_make_display(wnd, rgba_bytes);
@@ -597,7 +799,6 @@ drawXScreenSaver (JNIEnv *env, struct running_hack *rh)
if (! rh->xsft->fps_cb) rh->xsft->fps_cb = screenhack_do_fps;
} else {
rh->fpst = NULL;
- rh->xsft->fps_cb = 0;
}
if ((*env)->ExceptionOccurred(env)) abort();
@@ -834,7 +1035,7 @@ Java_org_jwz_xscreensaver_jwxyz_nativeResize (JNIEnv *env, jobject thiz,
}
jwxyz_window_resized (rh->dpy);
- } else if (rh->xsft->visual == DEFAULT_VISUAL) {
+ } else {
free_pixmap (rh, wnd);
create_pixmap (wnd, wnd);
XClearWindow (rh->dpy, wnd); // TODO: This is lame. Copy the bits.
@@ -877,6 +1078,8 @@ Java_org_jwz_xscreensaver_jwxyz_nativeDone (JNIEnv *env, jobject thiz)
prepare_context (rh);
+ if (rh->fpst)
+ rh->xsft->fps_free (rh->fpst);
if (rh->initted_p)
rh->xsft->free_cb (rh->dpy, rh->window, rh->closure);
if (rh->jwxyz_gl_p)
@@ -897,8 +1100,7 @@ Java_org_jwz_xscreensaver_jwxyz_nativeDone (JNIEnv *env, jobject thiz)
eglDestroyContext (rh->egl_display, rh->egl_ctx);
eglTerminate (rh->egl_display);
} else {
- if (rh->xsft->visual == DEFAULT_VISUAL)
- free_pixmap (rh, rh->window);
+ free_pixmap (rh, rh->window);
if (rh->native_window)
ANativeWindow_release (rh->native_window);
}
@@ -1375,6 +1577,12 @@ jwxyz_scale (Window main_window)
return 2;
}
+float
+jwxyz_font_scale (Window main_window)
+{
+ return jwxyz_scale (main_window);
+}
+
const char *
jwxyz_default_font_family (int require)
diff --git a/jwxyz/jwxyz-cocoa.h b/jwxyz/jwxyz-cocoa.h
index 5f2f61c..28f08b7 100644
--- a/jwxyz/jwxyz-cocoa.h
+++ b/jwxyz/jwxyz-cocoa.h
@@ -14,7 +14,7 @@
#import "XScreenSaverView.h"
-#ifdef USE_IPHONE
+#ifdef HAVE_IPHONE
# import <UIKit/UIKit.h>
# define NSView UIView
# define NSOpenGLContext EAGLContext
@@ -55,10 +55,10 @@ struct jwxyz_Drawable {
get leaked if a Pixmap CFRetains this.
*/
NSOpenGLContext *ogl_ctx; // OpenGL rendering context (OS X)
-# ifdef USE_IPHONE
+# ifdef HAVE_IPHONE
// TODO: Also on OS X as extensions.
GLuint gl_framebuffer, gl_renderbuffer;
-# endif // USE_IPHONE
+# endif // HAVE_IPHONE
CGImageRef cgi;
XRectangle frame;
union {
@@ -66,16 +66,16 @@ struct jwxyz_Drawable {
XScreenSaverView *view;
int last_mouse_x, last_mouse_y;
struct jwxyz_Drawable *current_drawable;
-# ifndef USE_IPHONE
+# ifndef HAVE_IPHONE
NSOpenGLPixelFormat *pixfmt;
GLint virtual_screen;
-# else // USE_IPHONE
+# else // HAVE_IPHONE
NSOpenGLContext *ogl_ctx_pixmap;
# endif
} window;
struct {
int depth;
-# ifndef USE_IPHONE
+# ifndef HAVE_IPHONE
NSOpenGLPixelBuffer *gl_pbuffer;
// GLuint blit_texture; // TODO: For blitting from Pbuffers
# endif
@@ -87,11 +87,11 @@ struct jwxyz_Drawable {
extern NSString *nsstring_from(const char *str, size_t len, int utf8_p);
-#ifdef USE_IPHONE
+#ifdef HAVE_IPHONE
extern void create_framebuffer (GLuint *gl_framebuffer,
GLuint *gl_renderbuffer);
extern void check_framebuffer_status (void);
-#endif // USE_IPHONE
+#endif // HAVE_IPHONE
#define jwxyz_window_view(w) ((w)->window.view)
diff --git a/jwxyz/jwxyz-cocoa.m b/jwxyz/jwxyz-cocoa.m
index 13666e7..f5bc551 100644
--- a/jwxyz/jwxyz-cocoa.m
+++ b/jwxyz/jwxyz-cocoa.m
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1991-2019 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright © 1991-2021 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
@@ -11,11 +11,10 @@
/* JWXYZ Is Not Xlib.
- But it's a bunch of function definitions that bear some resemblance to
- Xlib and that do Cocoa-ish or OpenGL-ish things that bear some resemblance
- to the things that Xlib might have done.
+ Cocoa glue for macOS and iOS: fonts and such.
- This code is used by both the original jwxyz.m and the new jwxyz-gl.c.
+ See the comment at the top of jwxyz-common.c for an explanation of
+ the division of labor between these various modules.
*/
#import "jwxyzI.h"
@@ -24,7 +23,7 @@
#include <stdarg.h>
-#ifdef USE_IPHONE
+#ifdef HAVE_IPHONE
# import <OpenGLES/ES1/gl.h>
# import <OpenGLES/ES1/glext.h>
# define NSOpenGLContext EAGLContext
@@ -99,7 +98,7 @@ jwxyz_scale_1 (Window main_window, BOOL fonts_p)
{
float scale = 1;
-# ifdef USE_IPHONE
+# ifdef HAVE_IPHONE
/* Since iOS screens are physically smaller than desktop screens, scale up
the fonts to make them more readable.
@@ -112,12 +111,12 @@ jwxyz_scale_1 (Window main_window, BOOL fonts_p)
if (scale < 1) // iPad Pro magnifies the backbuffer by 3x, which makes text
scale = 1; // excessively blurry in BSOD.
-# else // !USE_IPHONE
+# else // !HAVE_IPHONE
/* Desktop retina displays also need fonts doubled. */
scale = [main_window->window.view hackedContentScaleFactor:fonts_p];
-# endif // !USE_IPHONE
+# endif // !HAVE_IPHONE
return scale;
}
@@ -128,7 +127,7 @@ jwxyz_scale (Window main_window)
return jwxyz_scale_1 (main_window, FALSE);
}
-static float
+float
jwxyz_font_scale (Window main_window)
{
return jwxyz_scale_1 (main_window, TRUE);
@@ -193,7 +192,7 @@ utf8_metrics (Display *dpy, NSFont *nsfont, NSString *nsstr, XCharStruct *cs)
CGFloat advancement =
CTRunGetTypographicBounds (run, r, &ascent, &descent, &leading);
-# ifndef USE_IPHONE
+# ifndef HAVE_IPHONE
// Only necessary for when LCD smoothing is enabled, which iOS doesn't do.
bbox.origin.x -= 2.0/3.0;
bbox.size.width += 4.0/3.0;
@@ -234,7 +233,7 @@ utf8_metrics (Display *dpy, NSFont *nsfont, NSString *nsstr, XCharStruct *cs)
static NSArray *
font_family_members (NSString *family_name)
{
-# ifndef USE_IPHONE
+# ifndef HAVE_IPHONE
return [[NSFontManager sharedFontManager]
availableMembersOfFontFamily:family_name];
# else
@@ -275,7 +274,7 @@ try_font (NSFontTraitMask traits, NSFontTraitMask mask,
traits & NSFixedPitchFontMask ? JWXYZ_STYLE_MONOSPACE : 0)]);
}
-# ifndef USE_IPHONE
+# ifndef HAVE_IPHONE
for (unsigned k = 0; k != family_members.count; ++k) {
NSArray *member = [family_members objectAtIndex:k];
@@ -308,7 +307,7 @@ try_font (NSFontTraitMask traits, NSFontTraitMask mask,
return f;
}
}
-# else // USE_IPHONE
+# else // HAVE_IPHONE
// This trick needs iOS 3.1, see "Using SDK-Based Development".
Class has_font_descriptor = [UIFontDescriptor class];
@@ -331,7 +330,7 @@ try_font (NSFontTraitMask traits, NSFontTraitMask mask,
font_mask |= NSBoldFontMask;
if (MATCH(@"Italic") || MATCH(@"Oblique"))
font_mask |= NSItalicFontMask;
- if (MATCH(@"Courier"))
+ if (MATCH(@"Courier") || MATCH(@"monospace") || MATCH(@"fixed"))
font_mask |= NSFixedPitchFontMask;
}
@@ -370,7 +369,7 @@ static NSFont *
random_font (NSFontTraitMask traits, NSFontTraitMask mask, float size)
{
-# ifndef USE_IPHONE
+# ifndef HAVE_IPHONE
// Providing Unbold or Unitalic in the mask for availableFontNamesWithTraits
// returns an empty list, at least on a system with default fonts only.
NSArray *families = [[NSFontManager sharedFontManager]
@@ -395,7 +394,7 @@ random_font (NSFontTraitMask traits, NSFontTraitMask mask, float size)
families = new_families;
}
-# endif // USE_IPHONE
+# endif // HAVE_IPHONE
long n = [families count];
if (n <= 0) return 0;
@@ -563,7 +562,7 @@ jwxyz_render_text (Display *dpy, void *native_font,
void
jwxyz_get_pos (Window w, XPoint *xvpos, XPoint *xp)
{
-# ifdef USE_IPHONE
+# ifdef HAVE_IPHONE
xvpos->x = 0;
xvpos->y = 0;
@@ -573,7 +572,7 @@ jwxyz_get_pos (Window w, XPoint *xvpos, XPoint *xp)
xp->y = w->window.last_mouse_y;
}
-# else // !USE_IPHONE
+# else // !HAVE_IPHONE
NSWindow *nsw = [w->window.view window];
@@ -631,11 +630,11 @@ jwxyz_get_pos (Window w, XPoint *xvpos, XPoint *xp)
xp->y = (int) p.y;
}
-# endif // !USE_IPHONE
+# endif // !HAVE_IPHONE
}
-#ifdef USE_IPHONE
+#ifdef HAVE_IPHONE
void
check_framebuffer_status (void)
@@ -693,7 +692,7 @@ create_framebuffer (GLuint *gl_framebuffer, GLuint *gl_renderbuffer)
glBindRenderbufferOES (GL_RENDERBUFFER_OES, *gl_renderbuffer);
}
-#endif // USE_IPHONE
+#endif // HAVE_IPHONE
#if defined JWXYZ_QUARTZ
@@ -841,7 +840,7 @@ jwxyz_copy_area (Display *dpy, Drawable src, Drawable dst, GC gc,
/* Strange and ugly flickering when going the glCopyTexImage2D route on
OS X. (Early 2009 Mac mini, OS X 10.10)
*/
-# ifdef USE_IPHONE
+# ifdef HAVE_IPHONE
/* TODO: This might not still work. */
jwxyz_bind_drawable (dpy, dpy->main_window, src);
@@ -850,10 +849,10 @@ jwxyz_copy_area (Display *dpy, Drawable src, Drawable dst, GC gc,
jwxyz_bind_drawable (dpy, dpy->main_window, dst);
jwxyz_gl_copy_area_write_tex_image (dpy, gc, src_x, src_y,
width, height, dst_x, dst_y);
-# else // !USE_IPHONE
+# else // !HAVE_IPHONE
jwxyz_gl_copy_area_read_pixels (dpy, src, dst, gc,
src_x, src_y, width, height, dst_x, dst_y);
-# endif // !USE_IPHONE
+# endif // !HAVE_IPHONE
jwxyz_assert_gl ();
}
@@ -877,7 +876,7 @@ jwxyz_assert_gl ()
void
jwxyz_assert_drawable (Window main_window, Drawable d)
{
-#if !defined USE_IPHONE && !defined __OPTIMIZE__
+#if !defined HAVE_IPHONE && !defined __OPTIMIZE__
XScreenSaverView *view = main_window->window.view;
NSOpenGLContext *ogl_ctx = [view oglContext];
@@ -896,7 +895,7 @@ jwxyz_assert_drawable (Window main_window, Drawable d)
perror([[exception reason] UTF8String]);
jwxyz_abort();
}
-#endif // !USE_IPHONE && !__OPTIMIZE__
+#endif // !HAVE_IPHONE && !__OPTIMIZE__
}
@@ -925,7 +924,7 @@ jwxyz_bind_drawable (Window main_window, Drawable d)
jwxyz_assert_gl ();
jwxyz_assert_drawable (main_window, d);
-#if defined USE_IPHONE && !defined __OPTIMIZE__
+#if defined HAVE_IPHONE && !defined __OPTIMIZE__
Drawable current_drawable = main_window->window.current_drawable;
Assert (!current_drawable
|| current_drawable->ogl_ctx == [EAGLContext currentContext],
@@ -942,7 +941,7 @@ jwxyz_bind_drawable (Window main_window, Drawable d)
main_window->window.current_drawable = d;
/* Doing this repeatedly is probably not OK performance-wise. Probably. */
-#ifndef USE_IPHONE
+#ifndef HAVE_IPHONE
[d->ogl_ctx makeCurrentContext];
#else
[EAGLContext setCurrentContext:d->ogl_ctx];
@@ -973,7 +972,7 @@ XCreatePixmap (Display *dpy, Drawable d,
/* TODO: If Pixel buffers are not supported, do something about it. */
Window w = XRootWindow (dpy, 0);
-# ifndef USE_IPHONE
+# ifndef HAVE_IPHONE
p->ogl_ctx = [[NSOpenGLContext alloc]
initWithFormat:w->window.pixfmt
@@ -997,7 +996,7 @@ XCreatePixmap (Display *dpy, Drawable d,
mipMapLevel:0
currentVirtualScreen:w->window.virtual_screen];
-# else // USE_IPHONE
+# else // HAVE_IPHONE
p->ogl_ctx = w->window.ogl_ctx_pixmap;
@@ -1012,7 +1011,7 @@ XCreatePixmap (Display *dpy, Drawable d,
glBindFramebufferOES(GL_FRAMEBUFFER_OES, p->gl_framebuffer);
-# endif // USE_IPHONE
+# endif // HAVE_IPHONE
w->window.current_drawable = p;
glViewport (0, 0, width, height);
@@ -1033,16 +1032,16 @@ XFreePixmap (Display *d, Pixmap p)
Window w = RootWindow (d, 0);
-# ifndef USE_IPHONE
+# ifndef HAVE_IPHONE
CFRelease (p->ogl_ctx);
[p->ogl_ctx release];
CFRelease (p->pixmap.gl_pbuffer);
[p->pixmap.gl_pbuffer release];
-# else // USE_IPHONE
+# else // HAVE_IPHONE
glDeleteRenderbuffersOES (1, &p->gl_renderbuffer);
glDeleteFramebuffersOES (1, &p->gl_framebuffer);
-# endif // USE_IPHONE
+# endif // HAVE_IPHONE
if (w->window.current_drawable == p) {
w->window.current_drawable = NULL;
diff --git a/jwxyz/jwxyz-common.c b/jwxyz/jwxyz-common.c
index febb3b5..0b170f6 100644
--- a/jwxyz/jwxyz-common.c
+++ b/jwxyz/jwxyz-common.c
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1991-2019 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1991-2020 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
@@ -11,14 +11,48 @@
/* JWXYZ Is Not Xlib.
- But it's a bunch of function definitions that bear some resemblance to
- Xlib and that do Cocoa-ish or OpenGL-ish things that bear some resemblance
- to the things that Xlib might have done.
+ macOS and iOS:
+
+ jwxyz.m -- Xlib in terms of Quartz / Core Graphics rendering,
+ Renders into a CGContextRef that points to a CGImage
+ in CPU RAM.
+ jwxyz-cocoa.m -- Cocoa glue: fonts and such.
+
+ Android:
+
+ jwxyz-android.c -- Java / JNI glue. Renders into an FBO texture if
+ possible, otherwise an EGL PBuffer.
+
+ jwxyz-image.c -- Pixmaps implemented in CPU RAM, for OpenGL hacks.
+ Renders into an XImage, basically.
+
+ jwxyz-gl.c -- Pixmaps implemented in terms of OpenGL textures,
+ for X11 hacks (except kumppa, petri and slip).
+
+ Shared code:
+
+ jwxyz-common.c -- Most of the Xlib implementation, used by all 3 OSes.
+ jwzgles.c -- OpenGL 1.3 implemented in terms of OpenGLES 1.1.
+
+
+ Why two implemementations of Pixmaps for Android?
+
+ - GL hacks don't tend to need much in the way of Xlib, and having a
+ GL context to render Xlib alongside a GL context for rendering GL
+ seemed like trouble.
+
+ - X11 hacks render to a GL context because hardware acceleration tends
+ to work well with Xlib geometric stuff. Better framerates, lower
+ power.
+
+ Why not eliminate jwxyz-cocoa.m and use jwxyz-gl.c on macOS and iOS
+ as well?
+
+ - Yeah, maybe.
- This is the version of jwxyz for Android. The version used by MacOS
- and iOS is in jwxyz.m.
*/
+
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
@@ -1134,7 +1168,7 @@ try_xlfd_font (Display *dpy, const char *name, Font fid)
// This used to substitute Georgia for Times. Now it doesn't.
if (CMP ("random")) {
rand = True;
- } else if (CMP ("fixed")) {
+ } else if (CMP ("fixed") || CMP ("monospace")) {
require |= JWXYZ_STYLE_MONOSPACE;
family_name = "Courier";
family_name_size = strlen(family_name);
diff --git a/jwxyz/jwxyz-gl.c b/jwxyz/jwxyz-gl.c
index f1c13da..ed4c9c9 100644
--- a/jwxyz/jwxyz-gl.c
+++ b/jwxyz/jwxyz-gl.c
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1991-2018 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1991-2020 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
@@ -11,14 +11,14 @@
/* JWXYZ Is Not Xlib.
- But it's a bunch of function definitions that bear some resemblance to
- Xlib and that do OpenGL-ish things that bear some resemblance to the
- things that Xlib might have done.
+ Pixmaps implemented in terms of OpenGL textures, for Android X11 hacks.
+ Maybe this can someday be used on macOS and iOS as well.
- This is the version of jwxyz for Android. The version used by macOS
- and iOS is in jwxyz.m.
+ See the comment at the top of jwxyz-common.c for an explanation of
+ the division of labor between these various modules.
*/
+
/* Be advised, this is all very much a work in progress. */
/* There is probably no reason to ever implement indexed-color rendering here,
@@ -77,7 +77,7 @@
#include <wchar.h>
#ifdef HAVE_COCOA
-# ifdef USE_IPHONE
+# ifdef HAVE_IPHONE
# import <QuartzCore/QuartzCore.h>
# include <OpenGLES/ES1/gl.h>
# include <OpenGLES/ES1/glext.h>
@@ -91,6 +91,9 @@
# else
# include <GLES/gl.h>
# include <GLES/glext.h>
+# ifdef HAVE_GLES3
+# include <GLES3/gl3.h>
+# endif
# endif
#endif
@@ -186,7 +189,7 @@ jwxyz_set_matrices (Display *dpy, unsigned width, unsigned height,
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
-# if defined(USE_IPHONE) || defined(HAVE_ANDROID)
+# if defined(HAVE_IPHONE) || defined(HAVE_ANDROID)
if (window_p && ignore_rotation_p(dpy)) {
int o = (int) current_device_rotation();
@@ -917,7 +920,7 @@ jwxyz_gl_copy_area_read_tex_image (Display *dpy, unsigned src_height,
unsigned int width, unsigned int height,
int dst_x, int dst_y)
{
-# if defined HAVE_COCOA && !defined USE_IPHONE
+# if defined HAVE_COCOA && !defined HAVE_IPHONE
/* TODO: Does this help? */
/* glFinish(); */
# endif
diff --git a/jwxyz/jwxyz-image.c b/jwxyz/jwxyz-image.c
index b1b3332..dc644ee 100644
--- a/jwxyz/jwxyz-image.c
+++ b/jwxyz/jwxyz-image.c
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1991-2018 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1991-2020 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
@@ -11,11 +11,11 @@
/* JWXYZ Is Not Xlib.
- But it's a bunch of function definitions that bear some resemblance to
- Xlib and that do things to an XImage that bear some resemblance to the
- things that Xlib might have done.
+ Pixmaps implemented in CPU RAM, for Android OpenGL hacks.
+ Renders into an XImage, basically.
- This handles things when jwxyz-gl.c can't.
+ See the comment at the top of jwxyz-common.c for an explanation of
+ the division of labor between these various modules.
*/
#ifdef HAVE_CONFIG_H
diff --git a/jwxyz/jwxyz.h b/jwxyz/jwxyz.h
index fa76571..3eac567 100644
--- a/jwxyz/jwxyz.h
+++ b/jwxyz/jwxyz.h
@@ -73,6 +73,8 @@ typedef struct jwxyz_XCharStruct XCharStruct;
typedef struct jwxyz_XComposeStatus XComposeStatus;
typedef struct jwxyz_XPixmapFormatValues XPixmapFormatValues;
typedef struct jwxyz_XChar2b XChar2b;
+typedef struct jwxyz_XRegion * Region;
+typedef struct jwxyz_Box Box;
typedef union jwxyz_XEvent XEvent;
typedef struct jwxyz_XAnyEvent XAnyEvent;
@@ -286,6 +288,11 @@ typedef struct jwxyz_linked_point linked_point;
// #define GXnand 0xe /* NOT src OR NOT dst */
#define GXset 0xf /* 1 */
+#define Unsorted 0
+#define YSorted 1
+#define YXSorted 2
+#define YXBanded 3
+
#define XA_FONT 18
#define DefaultScreen(dpy) (0)
@@ -827,6 +834,17 @@ struct jwxyz_XChar2b {
unsigned char byte2;
};
+/* Xregion.h */
+struct jwxyz_Box {
+ short x1, x2, y1, y2;
+};
+
+struct jwxyz_XRegion {
+ long size;
+ long numRects;
+ Box *rects;
+ Box extents;
+};
struct jwxyz_vtbl {
Window (*root) (Display *);
diff --git a/jwxyz/jwxyz.m b/jwxyz/jwxyz.m
index c6a7af5..d25d580 100644
--- a/jwxyz/jwxyz.m
+++ b/jwxyz/jwxyz.m
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1991-2019 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1991-2020 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
@@ -11,13 +11,11 @@
/* JWXYZ Is Not Xlib.
- But it's a bunch of function definitions that bear some resemblance to
- Xlib and that do Cocoa-ish things that bear some resemblance to the
- things that Xlib might have done.
+ This file implements Xlib in terms of Quartz / Core Graphics rendering
+ for macOS and iOS.
- This is the original version of jwxyz for MacOS and iOS.
- The version used by Android is in jwxyz-gl.c and jwxyz-common.c.
- Both versions depend on jwxyz-cocoa.m.
+ See the comment at the top of jwxyz-common.c for an explanation of
+ the division of labor between these various modules.
*/
#ifdef JWXYZ_QUARTZ // entire file
@@ -26,7 +24,7 @@
#import <stdint.h>
#import <wchar.h>
-#ifdef USE_IPHONE
+#ifdef HAVE_IPHONE
# import <UIKit/UIKit.h>
# import <UIKit/UIScreen.h>
# import <QuartzCore/QuartzCore.h>
@@ -66,7 +64,7 @@ struct jwxyz_Display {
Visual visual;
struct jwxyz_sources_data *timers_data;
-# ifndef USE_IPHONE
+# ifndef HAVE_IPHONE
CGDirectDisplayID cgdpy; /* ...of the one and only Window, main_window.
This can change if the window is dragged to
a different screen. */
@@ -399,7 +397,7 @@ jwxyz_window_resized (Display *dpy)
{
Window w = dpy->main_window;
-# ifndef USE_IPHONE
+# ifndef HAVE_IPHONE
// Figure out which screen the window is currently on.
{
int wx, wy;
@@ -417,7 +415,7 @@ jwxyz_window_resized (Display *dpy)
}
Assert (dpy->cgdpy, "unable to find CGDisplay");
}
-# endif // USE_IPHONE
+# endif // HAVE_IPHONE
/*
{
@@ -1394,9 +1392,9 @@ jwxyz_draw_NSImage_or_CGImage (Display *dpy, Drawable d,
XRectangle *geom_ret, int exif_rotation)
{
CGImageRef cgi;
-# ifndef USE_IPHONE
+# ifndef HAVE_IPHONE
CGImageSourceRef cgsrc;
-# endif // USE_IPHONE
+# endif // HAVE_IPHONE
NSSize imgr;
CGContextRef cgc = d->cgc;
@@ -1406,7 +1404,7 @@ jwxyz_draw_NSImage_or_CGImage (Display *dpy, Drawable d,
NSImage *nsimg = (NSImage *) img_arg;
imgr = [nsimg size];
-# ifndef USE_IPHONE
+# ifndef HAVE_IPHONE
// convert the NSImage to a CGImage via the toll-free-bridging
// of NSData and CFData...
//
@@ -1416,9 +1414,9 @@ jwxyz_draw_NSImage_or_CGImage (Display *dpy, Drawable d,
CFDataRef cfdata = (CFDataRef) nsdata;
cgsrc = CGImageSourceCreateWithData (cfdata, NULL);
cgi = CGImageSourceCreateImageAtIndex (cgsrc, 0, NULL);
-# else // USE_IPHONE
+# else // HAVE_IPHONE
cgi = nsimg.CGImage;
-# endif // USE_IPHONE
+# endif // HAVE_IPHONE
} else {
cgi = (CGImageRef) img_arg;
@@ -1481,12 +1479,12 @@ jwxyz_draw_NSImage_or_CGImage (Display *dpy, Drawable d,
CGContextDrawImage (cgc, dst2, cgi);
CGContextRestoreGState (cgc);
-# ifndef USE_IPHONE
+# ifndef HAVE_IPHONE
if (nsimg_p) {
CFRelease (cgsrc);
CGImageRelease (cgi);
}
-# endif // USE_IPHONE
+# endif // HAVE_IPHONE
if (geom_ret) {
geom_ret->x = dst.origin.x;
@@ -1507,7 +1505,7 @@ jwxyz_png_to_ximage (Display *dpy, Visual *visual,
[NSData dataWithBytes:png_data
length:data_size]];
if (! img) return 0;
-#ifndef USE_IPHONE
+#ifndef HAVE_IPHONE
NSBitmapImageRep *bm = [NSBitmapImageRep
imageRepWithData:
[NSBitmapImageRep
@@ -1525,7 +1523,7 @@ jwxyz_png_to_ximage (Display *dpy, Visual *visual,
convert_mode_t mode = (([bm bitmapFormat] & NSAlphaFirstBitmapFormat)
? CONVERT_MODE_ROTATE_MASK
: 0);
-#else // USE_IPHONE
+#else // HAVE_IPHONE
CGImageRef cgi = [img CGImage];
if (!cgi) {
[img release];
@@ -1547,7 +1545,7 @@ jwxyz_png_to_ximage (Display *dpy, Visual *visual,
convert_mode_t mode = convert_mode_to_rgba (bitmap_info);
-#endif // USE_IPHONE
+#endif // HAVE_IPHONE
XImage *image = XCreateImage (dpy, visual, 32, ZPixmap, 0, 0,
width, height, 8, 0);
@@ -1567,7 +1565,7 @@ jwxyz_png_to_ximage (Display *dpy, Visual *visual,
[img release];
-#ifndef USE_IPHONE
+#ifndef HAVE_IPHONE
// [bm release];
# else
CGContextRelease (cgc);
diff --git a/jwxyz/jwxyzI.h b/jwxyz/jwxyzI.h
index f7560f7..6ff5d38 100644
--- a/jwxyz/jwxyzI.h
+++ b/jwxyz/jwxyzI.h
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1991-2018 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright © 1991-2021 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
@@ -52,6 +52,7 @@ extern unsigned int jwxyz_drawable_depth (Drawable d);
meaning of -[UIView contentScaleFactor] on iOS.
*/
extern float jwxyz_scale (Window main_window);
+extern float jwxyz_font_scale (Window main_window);
extern const char *jwxyz_default_font_family (int require);
extern void *jwxyz_load_native_font (Window main_window,
@@ -130,7 +131,7 @@ extern void jwxyz_quartz_copy_area (Display *dpy, Drawable src, Drawable dst,
# ifdef JWXYZ_GL
-# if defined(USE_IPHONE)
+# if defined(HAVE_IPHONE)
# include <OpenGLES/ES1/gl.h>
# elif defined(HAVE_COCOA)
# include <OpenGL/gl.h>
diff --git a/jwxyz/jwzgles.c b/jwxyz/jwzgles.c
index b26bc3a..26f1188 100644
--- a/jwxyz/jwzgles.c
+++ b/jwxyz/jwzgles.c
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2012-2019 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright © 2012-2021 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
@@ -9,9 +9,14 @@
* 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:
@@ -97,9 +102,17 @@
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:
@@ -152,6 +165,10 @@
#ifdef HAVE_JWZGLES /* whole file */
+#ifndef HAVE_GL
+# error HAVE_GL is undefined
+#endif
+
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -162,21 +179,30 @@
# 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"
@@ -1759,8 +1785,9 @@ jwzgles_glDrawBuffer (GLenum buf)
}
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 */
@@ -1770,6 +1797,29 @@ jwzgles_glDrawBuffer (GLenum buf)
}
+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.
*/
@@ -1966,15 +2016,15 @@ jwzgles_glEnd (void)
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;
@@ -2987,7 +3037,12 @@ jwzgles_glTexImage1D (GLenum target, GLint level,
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,
@@ -3010,8 +3065,13 @@ jwzgles_glTexImage2D (GLenum target,
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) {
@@ -4131,12 +4191,13 @@ jwzgles_gluCheckExtension (const GLubyte *ext_name, const GLubyte *ext_string)
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;
@@ -4288,7 +4349,7 @@ void jwzgles_##NAME (ARGS_##SIG) \
WRAP (glActiveTexture, I)
WRAP (glAlphaFunc, IF)
WRAP (glBlendFunc, II)
-//WRAP (glBlendColor, FFFF);
+/*WRAP (glBlendColor, FFFF);*/
WRAP (glClear, I)
WRAP (glClearColor, FFFF)
WRAP (glClearStencil, I)
@@ -4329,5 +4390,4 @@ WRAP (glTranslatef, FFF)
#define TYPE_IV GLuint
WRAP (glDeleteTextures, IIV)
-
#endif /* HAVE_JWZGLES - whole file */
diff --git a/jwxyz/jwzgles.h b/jwxyz/jwzgles.h
index 9c8d1e2..10c5bd8 100644
--- a/jwxyz/jwzgles.h
+++ b/jwxyz/jwzgles.h
@@ -21,7 +21,6 @@
# error: do not include this without HAVE_JWZGLES
#endif
-
#include "jwzglesI.h"
@@ -269,7 +268,6 @@
#define glRasterPos4iv jwzgles_glRasterPos4iv
#define glRasterPos4s jwzgles_glRasterPos4s
#define glRasterPos4sv jwzgles_glRasterPos4sv
-#define glReadBuffer jwzgles_glReadBuffer
#define glRectd jwzgles_glRectf
#define glRectdv jwzgles_glRectdv
#define glRectf jwzgles_glRectf
diff --git a/jwxyz/jwzglesI.h b/jwxyz/jwzglesI.h
index b90bad4..975b3ee 100644
--- a/jwxyz/jwzglesI.h
+++ b/jwxyz/jwzglesI.h
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2012-2019 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright © 2012-2021 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
@@ -184,6 +184,7 @@ extern void jwzgles_glDepthFunc (GLuint);
extern void jwzgles_glDepthMask (GLuint);
extern void jwzgles_glDisable (GLuint);
extern void jwzgles_glDrawArrays (GLuint, GLuint, GLuint);
+extern void jwzgles_glDrawElements (GLenum, GLsizei, GLenum, const GLvoid *);
extern GLboolean jwzgles_glIsEnabled (GLuint);
extern void jwzgles_glEnable (GLuint);
extern void jwzgles_glFrontFace (GLuint);
@@ -206,7 +207,6 @@ extern void jwzgles_glViewport (GLuint, GLuint, GLuint, GLuint);
extern void jwzgles_glTranslatef (GLfloat, GLfloat, GLfloat);
extern void jwzgles_glRotatef (GLfloat, GLfloat, GLfloat, GLfloat);
extern void jwzgles_glRotated (GLdouble, GLdouble x, GLdouble y, GLdouble z);
-extern void jwzgles_glReadBuffer (GLuint);
extern void jwzgles_glScalef (GLfloat, GLfloat, GLfloat);
extern void jwzgles_glColor3f (GLfloat, GLfloat, GLfloat);
extern void jwzgles_glColor4f (GLfloat, GLfloat, GLfloat, GLfloat);