Skip to content

Instantly share code, notes, and snippets.

@agrif
Created December 16, 2012 01:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save agrif/4302270 to your computer and use it in GitHub Desktop.
Save agrif/4302270 to your computer and use it in GitHub Desktop.
MacSlow's ARGB GLX visuals demo, archived here because the original site is down :(
/*******************************************************************************
**3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
** 10 20 30 40 50 60 70 80
**
** program:
** rgba-glx
**
** author:
** Mirco "MacSlow" Mueller <macslow@bangang.de>
**
** created:
** 8.4.2006
**
** last change:
** 10.4.2006
**
** notes:
** Creates a spinning sphere "floating" on the desktop. You need to run Xorg
** 7.0 in a Composite-enabled environment, xcompmgr, an nvidia card, the new
** 1.0-8756 driver and...
**
** Option "AddARGBGLXVisuals" "true"
**
** in the screen-section of your /etc/X11/xorg.conf. This is all different
** from using Xgl, compiz and xwinwrap. You don't need those for it to work.
** I would say that it will _not_ work under Xgl/compiz at all. You can move
** it around with your typical window-managers combo <Alt>-LMB-drag and quit
** with ESC.
**
** how to compile:
** gcc -Wall -g -DXK_MISCELLANY -lXi -lGL -lGLU -lXrender -lglut \
** rgba-glx.c -o rgba-glx
**
** what you need to compile:
** The whole set of development files for...
**
** Xorg 7.0 (including the Render-extension)
** OpenGL (obviously from nvidia)
** glut (I used freeglut)
**
** ideas:
** spinning 3D-logos for machines running on fairs for the "show off"-effect
** the most funky desktop-"widgets" you can think of
** a 3D-version of cairo-clock maybe ;)
** a sick gstreamer/GL-based video-player
** most dope-ish dock-like programs
** stylishly animated slash-screens for programs
** (add... better yet implement your own stuff here)
**
** license:
** I place this under the LGPL in the hope to see it getting leveraged in
** as many places as possible (e.g. gtkglext/mm), because this is some very
** cool feature, which should be useable as easy as possible!
**
** warranty/disclaimer:
** This code is provided "as is" take it or leave it. It is unsupported! It
** works for me but might not work for you. I will not take you by the hand
** and talk you through getting this thing compiled and running on your box.
** While I tried my best to keep it sane and save I cannot be held
** responsible if compiling/runnings this code will cause your pants to catch
** fire, your kitten dying a horrible death or else. Use it at your own risk!
** You have been warned!
**
*******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/keysymdef.h>
#include <X11/extensions/Xrender.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glx.h>
#include <GL/glut.h>
#define WIN_WIDTH 450
#define WIN_HEIGHT 450
#define FOV 45.0f
#define Z_NEAR 3.0f
/* this struct and the two defines are needed to be able to get rid of the wm
** decorations, if there's any simpler way to achieve this with fewer code I'll
** be glad to hear that, taken from gtk+ sources */
typedef struct {
unsigned long flags;
unsigned long functions;
unsigned long decorations;
long input_mode;
unsigned long status;
} MotifWmHints, MwmHints;
#define MWM_HINTS_FUNCTIONS (1L << 0)
#define MWM_HINTS_DECORATIONS (1L << 1)
/* this here is from the hints nvidia gives in their driver docs for utilizing
** the new AddARGBGLXVisuals option for xorg.conf */
int doubleBufferAttributes[] = {
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DOUBLEBUFFER, True,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_ALPHA_SIZE, 1,
GLX_DEPTH_SIZE, 1,
None
};
float g_fAngleZ = 0.0f;
/* this one tests if our window was already mapped (appeared on the display) */
Bool wait_for_notify (Display* pDisplay,
XEvent* pEvent,
XPointer arg)
{
return (pEvent->type == MapNotify) && (pEvent->xmap.window == (Window) arg);
}
/* resize the GL-context/viewport */
void resize_gl (int iWidth,
int iHeight)
{
glViewport (0, 0, iWidth, iHeight);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective (FOV, (float) (iWidth) / (float) (iHeight), 0.1f, 100.0f);
glMatrixMode (GL_MODELVIEW);
}
/* setup some initial states for our GL-context */
void init_gl (int iWidth,
int iHeight)
{
float fBGAlpha = 0.0f; /* background-opacity */
float afBGColor[] = {0.0f, 0.0f, 0.0f}; /* background-color itself */
/* the Render-extention expects premultiplied alpha colors */
glClearColor (fBGAlpha * afBGColor[0],
fBGAlpha * afBGColor[1],
fBGAlpha * afBGColor[2],
fBGAlpha);
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable (GL_DEPTH_TEST);
glLineWidth (1.5f);
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
glPolygonMode (GL_BACK, GL_FILL);
glPolygonMode (GL_FRONT, GL_LINE);
glDisable (GL_CULL_FACE);
glLightModelf (GL_LIGHT_MODEL_TWO_SIDE, 1.0f);
glShadeModel (GL_FLAT);
resize_gl (iWidth, iHeight);
glLoadIdentity ();
gluLookAt (0.0f, 0.0f, Z_NEAR,
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f);
glTranslatef (0.0f, 0.0f, -Z_NEAR);
}
/* the main function where the whole drawing takes place */
void draw_gl (Display* pDisplay,
Window window,
int iWhichGimmick)
{
GLfloat afFrontDiffuseMat[] = {1.0f, 0.5f, 0.25f, 1.0f};
GLfloat afBackDiffuseMat[] = {0.25f, 0.5f, 1.0f, 0.9f};
GLfloat afFrontDiffuseMat2[] = {0.5f, 0.25f, 1.0f, 1.0f};
GLfloat afBackDiffuseMat2[] = {1.0f, 0.25f, 0.5f, 0.9f};
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (iWhichGimmick == 1)
{
glPushMatrix ();
glTranslatef (0.0f, 0.0f, 3.0f);
glRotatef (g_fAngleZ, 0.0f, 0.0f, 1.0f);
glRotatef (0.5f * g_fAngleZ, 0.0f, 1.0f, 0.0f);
glRotatef (135.0f, 1.0f, 0.0f, 0.0f);
glMaterialfv (GL_FRONT, GL_DIFFUSE, afFrontDiffuseMat);
glMaterialfv (GL_BACK, GL_DIFFUSE, afBackDiffuseMat);
glutSolidSphere (1.0f, 24, 12);
glPopMatrix ();
}
else
{
glPushMatrix ();
glTranslatef (0.0f, 0.0f, 3.0f);
glRotatef (g_fAngleZ, 0.0f, 0.0f, 1.0f);
glRotatef (0.5f * g_fAngleZ, 0.0f, 1.0f, 0.0f);
glRotatef (135.0f, 1.0f, 0.0f, 0.0f);
glPolygonMode (GL_FRONT, GL_LINE);
glPolygonMode (GL_BACK, GL_FILL);
glMaterialfv (GL_FRONT, GL_DIFFUSE, afFrontDiffuseMat);
glMaterialfv (GL_BACK, GL_DIFFUSE, afBackDiffuseMat);
glScalef (0.5f, 0.5f, 0.5f);
glutSolidDodecahedron();
glPopMatrix ();
glMaterialfv (GL_FRONT, GL_DIFFUSE, afFrontDiffuseMat2);
glMaterialfv (GL_BACK, GL_DIFFUSE, afBackDiffuseMat2);
glPushMatrix ();
glTranslatef (0.0f, 0.0f, 3.0f);
glRotatef (1.2f * g_fAngleZ, 0.0f, 1.0f, 0.0f);
glRotatef (0.75f * g_fAngleZ, 1.0f, 1.0f, 0.0f);
glRotatef (221.0f, 1.0f, 0.0f, 0.0f);
glPolygonMode (GL_FRONT, GL_FILL);
glScalef (0.5f, 0.5f, 0.5f);
glutSolidOctahedron();
glPopMatrix ();
}
glXSwapBuffers (pDisplay, window);
}
int main (int argc,
char** argv)
{
Display* pDisplay = NULL;
Window window;
XEvent event;
XVisualInfo* pVisInfo;
XSetWindowAttributes windowAttribs;
GLXFBConfig* pFBConfigs;
GLXFBConfig renderFBConfig;
GLXContext glxContext;
GLXWindow glxWindow;
int windowAttribsMask;
int iNumOfFBConfigs;
int iRenderEventBase;
int iRenderErrorBase;
int i;
XRenderPictFormat* pPictFormat = NULL;
Bool bKeepGoing = False;
Atom hintsAtom = None;
unsigned char* pucData;
MotifWmHints newHints;
Atom typeAtom;
int iFormat;
unsigned long ulItems;
unsigned long ulBytesAfter;
Bool bGotEvent = False;
Bool bLMBPressed = False;
int iWhichGimmick = 1;
bzero ((void*) &newHints, sizeof (MotifWmHints));
/* check which object-gimmick should be drawn */
if (argc == 2)
iWhichGimmick = atoi (argv[1]);
/* open a connection to the X server */
pDisplay = XOpenDisplay (NULL);
if (pDisplay == NULL)
{
fprintf (stderr, "Unable to open a connection to the X server!\n");
return 1;
}
/* test for the RENDER extension */
if (!XRenderQueryExtension (pDisplay, &iRenderEventBase, &iRenderErrorBase))
{
fprintf (stderr, "Damn, no RENDER extension found!\n");
return 2;
}
/* look for a framebuffer configuration, only try to get a double
** buffered config */
pFBConfigs = glXChooseFBConfig (pDisplay,
DefaultScreen (pDisplay),
doubleBufferAttributes,
&iNumOfFBConfigs);
if (pFBConfigs == NULL)
{
fprintf (stderr, "Argl, we could not get an ARGB-visual!\n");
return 3;
}
/* try to find a GLX visual with alpha from the list of fb-configs */
for (i = 0; i < iNumOfFBConfigs; i++)
{
pVisInfo = glXGetVisualFromFBConfig (pDisplay, pFBConfigs[i]);
if (!pVisInfo)
continue;
pPictFormat = XRenderFindVisualFormat (pDisplay, pVisInfo->visual);
if (!pPictFormat)
continue;
if (pPictFormat->direct.alphaMask > 0)
{
fprintf (stderr, "Strike, found a GLX visual with alpha-support!\n");
pVisInfo = glXGetVisualFromFBConfig (pDisplay, pFBConfigs[i]);
renderFBConfig = pFBConfigs[i];
bKeepGoing = True;
break;
}
XFree (pVisInfo);
}
if (!bKeepGoing)
{
fprintf (stderr, "Crap, was not able to acquire a Render-compatible GLX-visual!\n");
return 4;
}
/* set some window-attributes before... */
windowAttribs.border_pixel = 0;
windowAttribs.event_mask = StructureNotifyMask |
ButtonPressMask |
ButtonReleaseMask |
KeyPressMask |
PointerMotionMask;
windowAttribs.colormap = XCreateColormap (pDisplay,
RootWindow (pDisplay,
pVisInfo->screen),
pVisInfo->visual,
AllocNone);
windowAttribsMask = CWBorderPixel | CWColormap | CWEventMask;
/* ... creating our application window */
window = XCreateWindow (pDisplay,
RootWindow (pDisplay, pVisInfo->screen),
0,
0,
WIN_WIDTH,
WIN_HEIGHT,
0,
pVisInfo->depth,
InputOutput,
pVisInfo->visual,
windowAttribsMask,
&windowAttribs);
/* create a GLX context for OpenGL rendering */
glxContext = glXCreateNewContext (pDisplay,
renderFBConfig,
GLX_RGBA_TYPE,
NULL,
True);
/* make sure to get a GLX window with the fb-config with render-support */
glxWindow = glXCreateWindow (pDisplay, renderFBConfig, window, NULL);
/* get rid of any window decorations */
hintsAtom = XInternAtom (pDisplay, "_MOTIF_WM_HINTS", True);
XGetWindowProperty (pDisplay,
window,
hintsAtom,
0,
sizeof (MotifWmHints) / sizeof (long),
False,
AnyPropertyType,
&typeAtom,
&iFormat,
&ulItems,
&ulBytesAfter,
&pucData);
newHints.flags = MWM_HINTS_DECORATIONS;
newHints.decorations = 0;
XChangeProperty (pDisplay,
window,
hintsAtom,
hintsAtom,
32,
PropModeReplace,
(unsigned char *) &newHints,
sizeof (MotifWmHints) / sizeof (long));
/* show the window on the display... */
XMapWindow (pDisplay, window);
/* ... and wait for it to appear */
XIfEvent (pDisplay, &event, wait_for_notify, (XPointer) window);
/* ensure that our GL-context is the one we'll draw to */
glXMakeContextCurrent (pDisplay, glxWindow, glxWindow, glxContext);
/* freeglut needs this, we later use glutSolidSphere() in draw_gl() */
glutInit (&argc, argv);
/* our custom setup-functions for GL */
init_gl (WIN_WIDTH, WIN_HEIGHT);
while (bKeepGoing)
{
/* check for events _and_ don't block! */
bGotEvent = XCheckWindowEvent (pDisplay,
window,
StructureNotifyMask |
ButtonPressMask |
ButtonReleaseMask |
KeyPressMask |
PointerMotionMask,
&event);
/* in case of an event handle it... */
if (bGotEvent)
{
switch (event.type)
{
/* only test for the ESC-key and exit */
case KeyPress :
if (XLookupKeysym (&event.xkey, 0) == XK_Escape)
bKeepGoing = False;
break;
/* some mouse button was pressed */
case ButtonPress:
if (event.xbutton.button == 1)
bLMBPressed = True;
break;
/* some mouse button was released */
case ButtonRelease:
if (event.xbutton.button == 1)
bLMBPressed = False;
break;
/* our window was moved or resized */
case ConfigureNotify :
resize_gl (event.xconfigure.width, event.xconfigure.height);
break;
/* move the window on mouse-motion */
case MotionNotify :
/* still need to finish this */
/*if (bLMBPressed)
XMoveWindow (pDisplay,
window,
event.xmotion.x_root,
event.xmotion.y_root);*/
break;
}
}
/* ... otherwise just draw/animate our sphere and wait a bit */
else
{
g_fAngleZ += 1.0f;
draw_gl (pDisplay, glxWindow, iWhichGimmick);
usleep (50000);
}
}
/* clean up */
XUnmapWindow (pDisplay, window);
XDestroyWindow (pDisplay, window);
XCloseDisplay (pDisplay);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment