diff options
author | Simon Rettberg | 2021-04-06 14:23:46 +0200 |
---|---|---|
committer | Simon Rettberg | 2021-04-06 14:23:46 +0200 |
commit | 26b6e4255d4b9ff79a6dca10de5bec7bfc8691f9 (patch) | |
tree | a51e1637554bcd84e63cccb1cb220c898a2c4ee8 /jwxyz | |
parent | 5.44 (diff) | |
download | xscreensaver-26b6e4255d4b9ff79a6dca10de5bec7bfc8691f9.tar.gz xscreensaver-26b6e4255d4b9ff79a6dca10de5bec7bfc8691f9.tar.xz xscreensaver-26b6e4255d4b9ff79a6dca10de5bec7bfc8691f9.zip |
xscreensaver 6.00
Diffstat (limited to 'jwxyz')
-rw-r--r-- | jwxyz/Makefile.in | 30 | ||||
-rw-r--r-- | jwxyz/jwxyz-android.c | 300 | ||||
-rw-r--r-- | jwxyz/jwxyz-cocoa.h | 16 | ||||
-rw-r--r-- | jwxyz/jwxyz-cocoa.m | 69 | ||||
-rw-r--r-- | jwxyz/jwxyz-common.c | 48 | ||||
-rw-r--r-- | jwxyz/jwxyz-gl.c | 21 | ||||
-rw-r--r-- | jwxyz/jwxyz-image.c | 10 | ||||
-rw-r--r-- | jwxyz/jwxyz.h | 18 | ||||
-rw-r--r-- | jwxyz/jwxyz.m | 42 | ||||
-rw-r--r-- | jwxyz/jwxyzI.h | 5 | ||||
-rw-r--r-- | jwxyz/jwzgles.c | 108 | ||||
-rw-r--r-- | jwxyz/jwzgles.h | 2 | ||||
-rw-r--r-- | jwxyz/jwzglesI.h | 4 |
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); |