X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fglx%2Fnoof.c;h=4e42840862fa65c408a9a9d6b977214025cb0027;hb=HEAD;hp=2132b7e8f5b91156d16365b2e18dac15cb0e77b1;hpb=6b1c86cf395f59389e4ece4ea8f4bea2c332745b;p=xscreensaver diff --git a/hacks/glx/noof.c b/hacks/glx/noof.c index 2132b7e8..4e428408 100644 --- a/hacks/glx/noof.c +++ b/hacks/glx/noof.c @@ -1,4 +1,4 @@ -/* noof, Copyright (c) 2004 Bill Torzewski +/* noof, Copyright (c) 2004-2018 Bill Torzewski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -16,11 +16,14 @@ #define DEFAULTS "*delay: 10000 \n" \ "*showFPS: False \n" \ "*fpsSolid: True \n" \ + "*doubleBuffer: False \n" \ + "*suppressRotationAnimation: True\n" \ -# define refresh_noof 0 +# define free_noof 0 # define release_noof 0 # define noof_handle_event 0 #include "xlockmore.h" +#include "pow2.h" #ifdef USE_GL /* whole file */ @@ -49,6 +52,8 @@ typedef struct { int tko; + GLuint screenshot_texture, tex_w, tex_h; + } noof_configuration; static noof_configuration *bps = NULL; @@ -117,10 +122,10 @@ static const float bladeratio[] = 0.22824, 0.21256, 0.19891, 0.18693, 0.17633, 0.16687, }; -static void +static int drawleaf(noof_configuration *bp, int l) { - + int polys = 0; int b, blades; float x, y; float wobble; @@ -137,7 +142,7 @@ drawleaf(noof_configuration *bp, int l) initshapes(bp, l); /* let it become reborn as something else */ bp->tko++; - return; + return polys; } { float w1 = sin(bp->geep[l] * 15.3 * M_PI / 180.0); wobble = 3.0 + 2.00 * sin(bp->geep[l] * 0.4 * M_PI / 180.0) + 3.94261 * w1; @@ -174,6 +179,7 @@ drawleaf(noof_configuration *bp, int l) glVertex2f(x, y); glVertex2f(x, -y); /* C */ glVertex2f(0.3, 0.0); /* D */ + polys += 2; glEnd(); /** @@ -186,11 +192,13 @@ drawleaf(noof_configuration *bp, int l) glVertex2f(x, y); glVertex2f(0.3, 0.0); /* D */ glVertex2f(x, -y); /* C */ + polys += 3; glEnd(); glDisable(GL_BLEND); glPopMatrix(); } + return polys; } static void @@ -373,6 +381,35 @@ draw_noof (ModeInfo *mi) return; glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context)); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + /* In the olden days, one could just render directly into the front buffer, + or fail to clear the back buffer and assume that one's bits were still + there. Not so on modern devices, particularly mobile. So to achieve + the effect of frame N+1 accumulating atop frame N, we must save and + restore a screenshot of frame N. + */ + if (bp->screenshot_texture) + { + GLfloat tw = MI_WIDTH(mi) / (GLfloat) bp->tex_w; + GLfloat th = MI_HEIGHT(mi) / (GLfloat) bp->tex_h; + glDisable (GL_BLEND); + glEnable (GL_TEXTURE_2D); + glBindTexture (GL_TEXTURE_2D, bp->screenshot_texture); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glBegin (GL_QUADS); + glTexCoord2f (0, 0); glVertex3f (0, 0, 0); + glTexCoord2f (tw, 0); glVertex3f (bp->wd, 0, 0); + glTexCoord2f (tw, th); glVertex3f (bp->wd, bp->ht, 0); + glTexCoord2f (0, th); glVertex3f (0, bp->ht, 0); + glEnd(); + glDisable (GL_TEXTURE_2D); + glClear (GL_DEPTH_BUFFER_BIT); + } + + mi->polygon_count = 0; + /** if((random() & 0xff) == 0x34){ glClear(GL_COLOR_BUFFER_BIT); @@ -393,15 +430,24 @@ draw_noof (ModeInfo *mi) for (i = 0; i < N_SHAPES; i++) { motionUpdate(bp, i); colorUpdate(bp, i); - drawleaf(bp, i); + mi->polygon_count += drawleaf(bp, i); } + if (bp->screenshot_texture) /* Store a screenshot into the texture. */ + { + glDisable (GL_BLEND); + glEnable (GL_TEXTURE_2D); + glBindTexture (GL_TEXTURE_2D, bp->screenshot_texture); + glCopyTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, 0, 0, + MI_WIDTH(mi), MI_HEIGHT(mi)); + check_gl_error("screenshot texture"); + glDisable (GL_TEXTURE_2D); + } + if (mi->fps_p) do_fps (mi); glFinish(); -/* For some reason this hack screws up on Cocoa if we try to double-buffer it. - It looks fine single-buffered, so let's just do that. */ -/* glXSwapBuffers(MI_DISPLAY(mi), MI_WINDOW(mi)); */ + glXSwapBuffers(MI_DISPLAY(mi), MI_WINDOW(mi)); } @@ -409,6 +455,7 @@ ENTRYPOINT void reshape_noof(ModeInfo *mi, int w, int h) { noof_configuration *bp = &bps[MI_SCREEN(mi)]; + char *s; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); @@ -428,7 +475,21 @@ reshape_noof(ModeInfo *mi, int w, int h) glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + if (!bp->screenshot_texture) + glGenTextures (1, &bp->screenshot_texture); + + glEnable (GL_TEXTURE_2D); + glBindTexture (GL_TEXTURE_2D, bp->screenshot_texture); + + bp->tex_w = to_pow2 (MI_WIDTH(mi)); + bp->tex_h = to_pow2 (MI_HEIGHT(mi)); + s = calloc (4, bp->tex_w * bp->tex_h); /* init with black */ + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, bp->tex_w, bp->tex_h, 0, + GL_RGBA, GL_UNSIGNED_BYTE, s); + check_gl_error ("texture generation"); + free (s); + glDisable (GL_TEXTURE_2D); + glClear (GL_COLOR_BUFFER_BIT); } ENTRYPOINT void @@ -437,26 +498,18 @@ init_noof (ModeInfo *mi) int i; noof_configuration *bp; - if (!bps) { - bps = (noof_configuration *) - calloc (MI_NUM_SCREENS(mi), sizeof (noof_configuration)); - if (!bps) { - fprintf(stderr, "%s: out of memory\n", progname); - exit(1); - } - } + MI_INIT (mi, bps); bp = &bps[MI_SCREEN(mi)]; bp->glx_context = init_GL(mi); - glDrawBuffer(GL_FRONT); - glClearColor(0.0, 0.0, 0.0, 1.0); glEnable(GL_LINE_SMOOTH); glShadeModel(GL_FLAT); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); for (i = 0; i < N_SHAPES; i++) initshapes(bp, i); + reshape_noof (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); }