Created
December 16, 2012 01:58
-
-
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 :(
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************************************************************************* | |
**3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 | |
** 10 20 30 40 50 60 70 80 | |
** | |
** program: | |
** rgba-glx | |
** | |
** author: | |
** Mirco "MacSlow" Mueller <[email protected]> | |
** | |
** 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