~ubuntu-branches/ubuntu/dapper/xscreensaver/dapper-updates

« back to all changes in this revision

Viewing changes to hacks/glx/flipscreen3d.c

  • Committer: Bazaar Package Importer
  • Author(s): Ralf Hildebrandt
  • Date: 2005-04-09 00:06:43 UTC
  • mfrom: (1.1.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20050409000643-z0abtifbt9s20pcc
Tags: 4.21-3
Patch by Joachim Breitner to check more frequently if DPMS kicked in (closes: #303374, #286664).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * flipscreen3d - takes snapshots of the screen and flips it around
 
3
 *
 
4
 * version 1.0 - Oct 24, 2001
 
5
 *
 
6
 * Copyright (C) 2001 Ben Buxton (bb@cactii.net)
 
7
 *
 
8
 * Permission to use, copy, modify, distribute, and sell this software and its
 
9
 * documentation for any purpose is hereby granted without fee, provided that
 
10
 * the above copyright notice appear in all copies and that both that
 
11
 * copyright notice and this permission notice appear in supporting
 
12
 * documentation.  No representations are made about the suitability of this
 
13
 * software for any purpose.  It is provided "as is" without express or
 
14
 * implied warranty.
 
15
 */
 
16
 
 
17
#include <X11/Intrinsic.h>
 
18
 
 
19
 
 
20
#ifdef STANDALONE
 
21
# define PROGCLASS                                      "FlipScreen3D"
 
22
# define HACK_INIT                                      init_screenflip
 
23
# define HACK_DRAW                                      draw_screenflip
 
24
# define HACK_RESHAPE                           reshape_screenflip
 
25
# define HACK_HANDLE_EVENT                              screenflip_handle_event
 
26
# define EVENT_MASK                                     PointerMotionMask
 
27
# define screenflip_opts                                     xlockmore_opts
 
28
/* insert defaults here */
 
29
 
 
30
#define DEFAULTS "*delay:     20000 \n" \
 
31
                 "*showFPS:   False \n" \
 
32
                 "*wireframe: False \n" \
 
33
                 "*useSHM:    True  \n"
 
34
 
 
35
# include "xlockmore.h"                         /* from the xscreensaver distribution */
 
36
#else  /* !STANDALONE */
 
37
# include "xlock.h"                                     /* from the xlockmore distribution */
 
38
#endif /* !STANDALONE */
 
39
 
 
40
/* lifted from lament.c */
 
41
#define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n))))
 
42
#define RANDSIGN() ((random() & 1) ? 1 : -1)
 
43
 
 
44
 
 
45
#ifdef USE_GL
 
46
 
 
47
#include <GL/glu.h>
 
48
 
 
49
int rotate;
 
50
 
 
51
int winw, winh;
 
52
int tw, th; /* texture width, height */
 
53
int tx, ty;
 
54
GLfloat min_tx, min_ty;
 
55
GLfloat max_tx, max_ty;
 
56
 
 
57
#define QW 12
 
58
#define QH 12
 
59
GLfloat qw = QW, qh = QH; /* q? are for the quad we'll draw */
 
60
GLfloat qx = -6 , qy = 6;
 
61
 
 
62
#undef countof
 
63
#define countof(x) (sizeof((x))/sizeof((*x)))
 
64
 
 
65
 
 
66
static XrmOptionDescRec opts[] = {
 
67
  {"+rotate", ".screenflip.rotate", XrmoptionNoArg, "false" },
 
68
  {"-rotate", ".screenflip.rotate", XrmoptionNoArg, "true" },
 
69
};
 
70
 
 
71
 
 
72
static argtype vars[] = {
 
73
  {&rotate, "rotate", "Rotate", "True", t_Bool},
 
74
};
 
75
 
 
76
 
 
77
 
 
78
ModeSpecOpt screenflip_opts = {countof(opts), opts, countof(vars), vars, NULL};
 
79
 
 
80
 
 
81
#ifdef USE_MODULES
 
82
ModStruct   screenflip_description =
 
83
{"screenflip", "init_screenflip", "draw_screenflip", "release_screenflip",
 
84
 "draw_screenflip", "init_screenflip", NULL, &screenflip_opts,
 
85
 1000, 1, 2, 1, 4, 1.0, "",
 
86
 "Screenflips", 0, NULL};
 
87
 
 
88
#endif
 
89
 
 
90
 
 
91
typedef struct {
 
92
  GLXContext *glx_context;
 
93
  Window window;
 
94
} Screenflip;
 
95
 
 
96
static Screenflip *screenflip = NULL;
 
97
 
 
98
#include <math.h>
 
99
#include <sys/time.h>
 
100
#include <stdio.h>
 
101
#include <stdlib.h>
 
102
#include "grab-ximage.h"
 
103
#include "gltrackball.h"
 
104
 
 
105
#ifndef M_PI
 
106
#define M_PI 3.14159265
 
107
#endif
 
108
 
 
109
static GLfloat viewer[] = {0.0, 0.0, 15.0};
 
110
 
 
111
int regrab = 0;
 
112
int fadetime = 0; /* fade before regrab */
 
113
 
 
114
static trackball_state *trackball;
 
115
static Bool button_down_p = False;
 
116
 
 
117
 
 
118
Bool
 
119
screenflip_handle_event (ModeInfo *mi, XEvent *event)
 
120
{
 
121
  if (event->xany.type == ButtonPress &&
 
122
      event->xbutton.button == Button1)
 
123
    {
 
124
      button_down_p = True;
 
125
      gltrackball_start (trackball,
 
126
                         event->xbutton.x, event->xbutton.y,
 
127
                         MI_WIDTH (mi), MI_HEIGHT (mi));
 
128
      return True;
 
129
    }
 
130
  else if (event->xany.type == ButtonRelease &&
 
131
           event->xbutton.button == Button1)
 
132
    {
 
133
      button_down_p = False;
 
134
      return True;
 
135
    }
 
136
  else if (event->xany.type == ButtonPress &&
 
137
           (event->xbutton.button == Button4 ||
 
138
            event->xbutton.button == Button5))
 
139
    {
 
140
      gltrackball_mousewheel (trackball, event->xbutton.button, 10,
 
141
                              !!event->xbutton.state);
 
142
      return True;
 
143
    }
 
144
  else if (event->xany.type == MotionNotify &&
 
145
           button_down_p)
 
146
    {
 
147
      gltrackball_track (trackball,
 
148
                         event->xmotion.x, event->xmotion.y,
 
149
                         MI_WIDTH (mi), MI_HEIGHT (mi));
 
150
      return True;
 
151
    }
 
152
 
 
153
  return False;
 
154
}
 
155
 
 
156
 
 
157
/* draw the texture mapped quad (actually two back to back)*/
 
158
void showscreen(int frozen, int wire)
 
159
{
 
160
  static GLfloat r = 1, g = 1, b = 1, a = 1;
 
161
  GLfloat x, y, w, h;
 
162
  /* static int stretch; */
 
163
  static GLfloat stretch_val_x = 0, stretch_val_y = 0;
 
164
  static GLfloat stretch_val_dx = 0, stretch_val_dy = 0;
 
165
  /* static int stretch_x = 0, stretch_y = 0; */
 
166
 
 
167
  if (fadetime) {
 
168
/*    r -= 0.02; g -= 0.02; b -= 0.02; */
 
169
    a -= 0.02;
 
170
    if (a < 0) {
 
171
      regrab = 1;
 
172
      fadetime = 0;
 
173
    }
 
174
  } else if (a < 0) {
 
175
    r = g = b = a = 1;
 
176
    stretch_val_x = stretch_val_y = stretch_val_dx = stretch_val_dy = 0;
 
177
  }
 
178
  if (stretch_val_dx == 0 && !frozen && !(random() % 25))
 
179
    stretch_val_dx = (float)(random() % 100) / 5000;
 
180
  if (stretch_val_dy == 0 && !frozen && !(random() % 25))
 
181
    stretch_val_dy = (float)(random() % 100) / 5000;
 
182
    
 
183
  x = qx;
 
184
  y = qy;
 
185
  w = qx+qw;
 
186
  h = qy-qh;
 
187
 
 
188
  if (!frozen) {
 
189
     w *= sin (stretch_val_x) + 1;
 
190
     x *= sin (stretch_val_x) + 1;
 
191
     if (!button_down_p) {
 
192
     if (!fadetime) stretch_val_x += stretch_val_dx;
 
193
     if (stretch_val_x > 2*M_PI && !(random() % 5))
 
194
       stretch_val_dx = (float)(random() % 100) / 5000;
 
195
     else
 
196
       stretch_val_x -= 2*M_PI;
 
197
     }
 
198
 
 
199
     if (!button_down_p && !fadetime) stretch_val_y += stretch_val_dy;
 
200
     h *= sin (stretch_val_y) / 2 + 1;
 
201
     y *= sin (stretch_val_y) / 2 + 1;
 
202
     if (!button_down_p) {
 
203
     if (stretch_val_y > 2*M_PI && !(random() % 5))
 
204
       stretch_val_dy = (float)(random() % 100) / 5000;
 
205
     else
 
206
       stretch_val_y -= 2*M_PI;
 
207
     }
 
208
  }
 
209
 
 
210
  glColor4f(r, g, b, a);
 
211
 
 
212
  if (!wire)
 
213
    {
 
214
      glEnable(GL_TEXTURE_2D);
 
215
      glEnable(GL_BLEND);
 
216
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
217
      glDepthMask(GL_FALSE);
 
218
    }
 
219
 
 
220
  glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
 
221
 
 
222
  glNormal3f(0, 0, 1);
 
223
  glTexCoord2f(max_tx, max_ty); glVertex3f(w, h, 0);
 
224
  glTexCoord2f(max_tx, min_ty); glVertex3f(w, y, 0);
 
225
  glTexCoord2f(min_tx, min_ty); glVertex3f(x, y, 0);
 
226
  glTexCoord2f(min_tx, max_ty); glVertex3f(x, h, 0);
 
227
 
 
228
  glNormal3f(0, 0, -1);
 
229
  glTexCoord2f(min_tx, min_ty); glVertex3f(x, y, -0.05);
 
230
  glTexCoord2f(max_tx, min_ty); glVertex3f(w, y, -0.05);
 
231
  glTexCoord2f(max_tx, max_ty); glVertex3f(w, h, -0.05);
 
232
  glTexCoord2f(min_tx, max_ty); glVertex3f(x, h, -0.05);
 
233
  glEnd();
 
234
 
 
235
 
 
236
  glDisable(GL_TEXTURE_2D);
 
237
  glDepthMask(GL_TRUE);
 
238
 
 
239
  glBegin(GL_LINE_LOOP);
 
240
   glVertex3f(x, y, 0);
 
241
   glVertex3f(x, h, 0);
 
242
   glVertex3f(w, h, 0);
 
243
   glVertex3f(w, y, 0);
 
244
 glEnd();
 
245
  glDisable(GL_BLEND);
 
246
 
 
247
}
 
248
 
 
249
/* This function is responsible for 'zooming back' the square after
 
250
 * a new chunk has been grabbed with getSnapshot(), and positioning
 
251
 * it suitably on the screen. Once positioned (where we begin to rotate),
 
252
 * it just does a glTranslatef() and returns 1
 
253
 */
 
254
 
 
255
int inposition(void)
 
256
{
 
257
  static GLfloat curx, cury, curz = 0;
 
258
  GLfloat wx;
 
259
  GLfloat wy;
 
260
  wx = 0 - (qw/2);
 
261
  wy = (qh/2);
 
262
 
 
263
  if (curx == 0) curx = qx;
 
264
  if (cury == 0) cury = qy;
 
265
  if (regrab) {
 
266
     curz = 0;
 
267
     curx = qx;
 
268
     cury = qy;
 
269
     regrab = 0;
 
270
  }
 
271
  if (curz > -10 || curx > wx + 0.1 || curx < wx - 0.1 ||
 
272
         cury > wy + 0.1 || cury < wy - 0.1) {
 
273
    if (curz > -10)
 
274
      curz -= 0.05;
 
275
    if (curx > wx) {
 
276
       qx -= 0.02;
 
277
       curx -= 0.02;
 
278
    }
 
279
    if (curx < wx) {
 
280
       qx += 0.02;
 
281
       curx += 0.02;
 
282
    }
 
283
    if (cury > wy) {
 
284
       qy -= 0.02;
 
285
       cury -= 0.02;
 
286
    }
 
287
    if (cury < wy) {
 
288
       qy += 0.02;
 
289
       cury += 0.02;
 
290
    }
 
291
    glTranslatef(0, 0, curz);
 
292
    return 0;
 
293
  }
 
294
  glTranslatef(0, 0, curz);
 
295
  return 1;
 
296
 
 
297
}
 
298
 
 
299
void drawgrid(void)
 
300
{
 
301
  int i;
 
302
 
 
303
  glColor3f(0, 0.7, 0);
 
304
  glBegin(GL_LINES);
 
305
  for (i = 0 ; i <= 50; i+=2) {
 
306
      glVertex3f( -25, -15, i-70);
 
307
      glVertex3f( 25, -15, i-70);
 
308
      glVertex3f( i-25, -15, -70);
 
309
      glVertex3f( i-25, -15, -20);
 
310
  }
 
311
  glEnd();
 
312
}
 
313
 
 
314
void display(int wire)
 
315
{
 
316
  static GLfloat rx=1, ry=1, rz=0;
 
317
  static GLfloat rot = 0;
 
318
  static GLfloat drot = 0;
 
319
  static GLfloat odrot = 1;
 
320
  static GLfloat ddrot = 0;
 
321
  static float theta = 0, rho = 0, dtheta = 0, drho = 0, gamma = 0, dgamma = 0;
 
322
  static GLfloat orot;
 
323
  int frozen;
 
324
 
 
325
  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
 
326
  glLoadIdentity();
 
327
  gluLookAt(viewer[0], viewer[1], viewer[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
 
328
  glPushMatrix();
 
329
 
 
330
  if (inposition()) {
 
331
    frozen = 0;
 
332
    glTranslatef(5 * sin(theta), 5 * sin(rho), 10 * cos(gamma) - 10);
 
333
/* randomly change the speed */
 
334
    if (!button_down_p && !(random() % 300)) {
 
335
      if (random() % 2)
 
336
        drho = 1/60 - (float)(random() % 100)/3000;
 
337
      if (random() % 2)
 
338
        dtheta = 1/60 - (float)(random() % 100)/3000;
 
339
      if (random() % 2)
 
340
        dgamma = 1/60 - (float)(random() % 100)/3000;
 
341
    }
 
342
    gltrackball_rotate (trackball);
 
343
    if (rotate) glRotatef(rot, rx, ry, rz);
 
344
/* update variables with each frame */
 
345
    if(!button_down_p && !fadetime) {
 
346
      theta += dtheta;
 
347
      rho += drho;
 
348
      gamma += dgamma;
 
349
      rot += drot;
 
350
      drot += ddrot;
 
351
    }
 
352
/* dont let our rotation speed get too high */
 
353
    if (drot > 5 && ddrot > 0)
 
354
        ddrot = 0 - (GLfloat)(random() % 100) / 1000;
 
355
    else if (drot < -5 && ddrot < 0)
 
356
        ddrot = (GLfloat)(random() % 100) / 1000;
 
357
  } else { /* reset some paramaters */
 
358
    ddrot = 0.05 - (GLfloat)(random() % 100) / 1000;
 
359
    theta = rho = gamma = 0;
 
360
    rot = 0;
 
361
    frozen = 1;
 
362
  }
 
363
  if (!button_down_p && !fadetime && (rot >= 360 || rot <= -360) && !(random() % 7)) { /* rotate  change */
 
364
    rx = (GLfloat)(random() % 100) / 100;
 
365
    ry = (GLfloat)(random() % 100) / 100;
 
366
    rz = (GLfloat)(random() % 100) / 100;
 
367
  }
 
368
  if (odrot * drot < 0 && tw < winw && !(random() % 10)) {
 
369
    fadetime = 1;                /* randomly fade and get new snapshot */
 
370
  }
 
371
  orot = rot;
 
372
  odrot = drot;
 
373
  if (rot > 360 || rot < -360) /* dont overflow rotation! */
 
374
    rot -= rot;
 
375
  showscreen(frozen, wire);
 
376
  glPopMatrix();
 
377
  glFlush();
 
378
}
 
379
 
 
380
void reshape_screenflip(ModeInfo *mi, int width, int height)
 
381
{
 
382
 glViewport(0,0,(GLint)width, (GLint) height);
 
383
 glMatrixMode(GL_PROJECTION);
 
384
 glLoadIdentity();
 
385
 gluPerspective(45, 1, 2.0, 85);
 
386
 glMatrixMode(GL_MODELVIEW);
 
387
 winw = width;
 
388
 winh = height;
 
389
}
 
390
 
 
391
void getSnapshot (ModeInfo *modeinfo)
 
392
{
 
393
  Bool mipmap_p = True;
 
394
  XRectangle geom;
 
395
  int iw, ih;
 
396
 
 
397
  if (MI_IS_WIREFRAME(modeinfo))
 
398
    return;
 
399
 
 
400
  if (! screen_to_texture (modeinfo->xgwa.screen, modeinfo->window, 0, 0,
 
401
                           mipmap_p, NULL, &geom, &iw, &ih, &tw, &th))
 
402
    exit (1);
 
403
 
 
404
  min_tx = (GLfloat) geom.x / tw;
 
405
  min_ty = (GLfloat) geom.y / th;
 
406
  max_tx = (GLfloat) (geom.x + geom.width)  / tw;
 
407
  max_ty = (GLfloat) (geom.y + geom.height) / th;
 
408
 
 
409
  qx = -QW/2 + ((GLfloat) geom.x * QW / iw);
 
410
  qy =  QH/2 - ((GLfloat) geom.y * QH / ih);
 
411
  qw = QW * ((GLfloat) geom.width  / iw);
 
412
  qh = QH * ((GLfloat) geom.height / ih);
 
413
 
 
414
  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
415
  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
 
416
                   (mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR));
 
417
}
 
418
 
 
419
void init_screenflip(ModeInfo *mi)
 
420
{
 
421
  int screen = MI_SCREEN(mi);
 
422
  Screenflip *c;
 
423
 
 
424
 if (screenflip == NULL) {
 
425
   if ((screenflip = (Screenflip *) calloc(MI_NUM_SCREENS(mi),
 
426
                                        sizeof(Screenflip))) == NULL)
 
427
          return;
 
428
 }
 
429
 c = &screenflip[screen];
 
430
 c->window = MI_WINDOW(mi);
 
431
 
 
432
 trackball = gltrackball_init ();
 
433
 
 
434
 if ((c->glx_context = init_GL(mi)) != NULL) {
 
435
      reshape_screenflip(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
 
436
 } else {
 
437
     MI_CLEARWINDOW(mi);
 
438
 }
 
439
 winh = MI_WIN_HEIGHT(mi);
 
440
 winw = MI_WIN_WIDTH(mi);
 
441
 glClearColor(0.0,0.0,0.0,0.0);
 
442
 
 
443
 if (! MI_IS_WIREFRAME(mi))
 
444
   {
 
445
     glShadeModel(GL_SMOOTH);
 
446
     glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
 
447
     glEnable(GL_DEPTH_TEST);
 
448
     glEnable(GL_CULL_FACE);
 
449
     glCullFace(GL_BACK);
 
450
     glDisable(GL_LIGHTING);
 
451
   }
 
452
 
 
453
 getSnapshot(mi);
 
454
}
 
455
 
 
456
void draw_screenflip(ModeInfo *mi)
 
457
{
 
458
  Screenflip *c = &screenflip[MI_SCREEN(mi)];
 
459
  Window w = MI_WINDOW(mi);
 
460
  Display *disp = MI_DISPLAY(mi);
 
461
 
 
462
  if (!c->glx_context)
 
463
      return;
 
464
 
 
465
 glXMakeCurrent(disp, w, *(c->glx_context));
 
466
 
 
467
  if (regrab)
 
468
    getSnapshot(mi);
 
469
 
 
470
  display(MI_IS_WIREFRAME(mi));
 
471
 
 
472
  if(mi->fps_p) do_fps(mi);
 
473
  glFinish(); 
 
474
  glXSwapBuffers(disp, w);
 
475
}
 
476
 
 
477
void release_screenflip(ModeInfo *mi)
 
478
{
 
479
  if (screenflip != NULL) {
 
480
   (void) free((void *) screenflip);
 
481
   screenflip = NULL;
 
482
  }
 
483
  FreeAllGL(MI);
 
484
}
 
485
 
 
486
#endif