summaryrefslogtreecommitdiffstats
path: root/hacks/glx/stonerview.c
blob: 880ef01b78cc1c9e48a197489ea3e4df621fd3b8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/* StonerView: An eccentric visual toy.
   Copyright 1998-2001 by Andrew Plotkin (erkyrath@eblong.com)

   For the latest version, source code, and links to more of my stuff, see:
   http://www.eblong.com/zarf/stonerview.html

   Permission to use, copy, modify, distribute, and sell this software and its
   documentation for any purpose is hereby granted without fee, provided that
   the above copyright notice appear in all copies and that both that
   copyright notice and this permission notice appear in supporting
   documentation.  No representations are made about the suitability of this
   software for any purpose.  It is provided "as is" without express or 
   implied warranty.
*/

/* Ported away from GLUT (so that it can do `-root' and work with xscreensaver)
   by Jamie Zawinski <jwz@jwz.org>, 22-Jan-2001.

   Revamped to work in the xlockmore framework so that it will also work
   with the MacOS X port of xscreensaver by jwz, 21-Feb-2006.
 */

#define DEFAULTS	"*delay:	20000       \n" \
			"*showFPS:      False       \n" \
			"*wireframe:    False       \n"

# define release_stonerview 0
#undef countof
#define countof(x) (sizeof((x))/sizeof((*x)))

#include "xlockmore.h"

#ifdef USE_GL /* whole file */

#include "stonerview.h"
#include "gltrackball.h"

#define DEF_TRANSPARENT "True"

typedef struct {
  GLXContext *glx_context;
  stonerview_state *st;
  trackball_state *trackball;
  Bool button_down_p;
} stonerview_configuration;

static stonerview_configuration *bps = NULL;

static Bool transparent_p;


static XrmOptionDescRec opts[] = {
  { "-transparent",   ".transparent",   XrmoptionNoArg, "True" },
  { "+transparent",   ".transparent",   XrmoptionNoArg, "False" },
};

static argtype vars[] = {
  {&transparent_p, "transparent", "Transparent", DEF_TRANSPARENT, t_Bool},
};

ENTRYPOINT ModeSpecOpt stonerview_opts = {countof(opts), opts, countof(vars), vars, NULL};


ENTRYPOINT void
reshape_stonerview (ModeInfo *mi, int width, int height)
{
  GLfloat h = (GLfloat) height / (GLfloat) width;

  glViewport(0, 0, (GLint) width, (GLint) height);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glTranslatef(0.0, 0.0, -40.0);
}


ENTRYPOINT void 
init_stonerview (ModeInfo *mi)
{
  stonerview_configuration *bp;

  MI_INIT (mi, bps);

  bp = &bps[MI_SCREEN(mi)];

  bp->glx_context = init_GL(mi);

  bp->trackball = gltrackball_init (False);
  bp->st = stonerview_init_view(MI_IS_WIREFRAME(mi), transparent_p);
  stonerview_init_move(bp->st);

  reshape_stonerview (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
  clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */
}


ENTRYPOINT void
draw_stonerview (ModeInfo *mi)
{
  stonerview_configuration *bp = &bps[MI_SCREEN(mi)];

  glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));

  glPushMatrix ();
  glRotatef( current_device_rotation(), 0, 0, 1);
  gltrackball_rotate (bp->trackball);

# ifdef HAVE_MOBILE	/* Keep it the same relative size when rotated. */
  {
    GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
    int o = (int) current_device_rotation();
    if (o != 0 && o != 180 && o != -180)
      glScalef (h, h, h);
  }
# endif

  stonerview_win_draw(bp->st);
  if (! bp->button_down_p)
    stonerview_move_increment(bp->st);
  glPopMatrix ();

  mi->polygon_count = NUM_ELS;
  if (mi->fps_p) do_fps (mi);
  glFinish();

  glXSwapBuffers(MI_DISPLAY (mi), MI_WINDOW(mi));
}

ENTRYPOINT void
free_stonerview (ModeInfo *mi)
{
  stonerview_configuration *bp = &bps[MI_SCREEN(mi)];
  if (bp->st)
    stonerview_win_release (bp->st);
}

ENTRYPOINT Bool
stonerview_handle_event (ModeInfo *mi, XEvent *event)
{
  stonerview_configuration *bp = &bps[MI_SCREEN(mi)];

  if (gltrackball_event_handler (event, bp->trackball,
                                 MI_WIDTH (mi), MI_HEIGHT (mi),
                                 &bp->button_down_p))
    return True;

  return False;
}

XSCREENSAVER_MODULE ("StonerView", stonerview)

#endif /* USE_GL */