Please note that I am not interested in updating the code or anything as it
is a quite old and only used in development. I realise it could be done
'nicer' :)
I hope this program demonstrates how powerful X-Windows is as a development
platform and illustrates the similarity to DOS's mode13h.
It should compile on all X11 based machines, including SGI's, but I haven't
tested it :( Could some kind soul please let me know how it does on other
X11 setups.
Also, it's got a timer on it that gives you a real-time frame counter. On my
machine, a P5-100 running 3.1.2E XFree86 I get about 250fps (4 milliseconds
per frame). Who said a windowing environment is slow :)
Usual programmers disclaimer applies: I won't be responsible if this program
blows up your house, causes loss of data, etc. If you want to be safe, don't
run it as root. I've had no problems though.
If anyone manages to do something nice with it, or similar, I'd love to hear
from them :)
Enjoy,
Jon.
-----------------------------------8<----------------------------------------
/*
(C) Jon Raymond 1995
j...@neurodne.demon.co.uk
Needs the MIT-SHM extension.
BadMatch on any server >256 colours.
To compile:
gcc -O2 example.c -lm -lX11 -lXext
Hope it helps...
*/
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/time.h>
#include <X11/extensions/XShm.h>
#define WIDTH 320
#define HEIGHT 200
Display *disp;
Window window;
Pixmap pixmap;
GC gc;
XImage *ximage;
XShmSegmentInfo shminfo;
char *colourmap;
void main()
{
XSetWindowAttributes attributes;
XSizeHints hint;
XWMHints wmhints;
XEvent event;
XColor xcolor[256];
Colormap colmap;
Visual *visual;
int screen,i,j,timing,x,y;
unsigned long attribute_mask;
disp=XOpenDisplay(0);
if(disp==(Display *) NULL){
printf("Unable to open display...\n");
exit(2);
}
if(!XShmQueryExtension(disp)){
printf("I need the MIT-Shm Extension\n");
getout();
exit(2);
}
else printf("Found shared memory extension...\n");
hint.x=150;
hint.y=200;
hint.width=WIDTH;
hint.height=HEIGHT;
hint.flags=PPosition|PSize;
screen=DefaultScreen(disp);
attributes.background_pixel=WhitePixel(disp,screen);
attributes.border_pixel=BlackPixel(disp,screen);
attributes.event_mask=0;
attribute_mask=CWBackPixel|CWBorderPixel|CWEventMask;
gc=DefaultGC(disp,screen);
window=XCreateWindow(disp,DefaultRootWindow(disp),150,200,
WIDTH,HEIGHT,0,CopyFromParent,
InputOutput,CopyFromParent,
attribute_mask,&attributes);
ximage=XShmCreateImage(disp,visual,8,ZPixmap,NULL,&shminfo,
WIDTH,HEIGHT);
shminfo.shmid=shmget(IPC_PRIVATE,ximage->bytes_per_line*ximage->height,
IPC_CREAT|0777);
shminfo.shmaddr=ximage->data=shmat(shminfo.shmid,0,0);
shminfo.readOnly=True;
XShmAttach(disp,&shminfo);
printf("MIT-SHM: Shared memory KID=%d, at=%p\n",shminfo.shmid,shminfo.shmaddr);
colourmap=ximage->data;
XSetStandardProperties(disp,window,"By j...@neurodne.demon.co.uk",
"j...@neurodne.demon.co.uk",None,0,0,&hint);
wmhints.flags=InputHint;wmhints.input=True;
XSetWMHints(disp,window,&wmhints);
XSelectInput(disp,window,ButtonPress|KeyPressMask);
colmap=XCreateColormap(disp,window,DefaultVisual(disp,screen),AllocAll);
for(i=0;i<256;i++){
xcolor[i].flags=DoRed|DoGreen|DoBlue;
xcolor[i].red=(i)<<9;
xcolor[i].green=(i)<<9;
xcolor[i].blue=(i)<<9;
xcolor[i].pixel=i;
XStoreColor(disp,colmap,&xcolor[i]);
}
XInstallColormap(disp,colmap);
XSetWindowColormap(disp,window,colmap);
XMapRaised(disp,window);
XFlush(disp);
printf("Hit return to start...\n");
x=i=1; y=j=1;
while(1){
timing=GetTimeInMs();
x+=i; y+=j;
if(x>WIDTH-33) i=-1;
if(y>HEIGHT-33) j=-1;
if(x<0) i=1;
if(y<0) j=1;
putsquare(x,y,colourmap);
XNextEvent(disp,&event);
if(event.type==ButtonPress) return;
XShmPutImage(disp,window,gc,ximage,0,0,0,0,WIDTH,HEIGHT,1);
bzero(colourmap,WIDTH*HEIGHT);
timing=GetTimeInMs()-timing;
printf(" %dMs %d fps \r",timing,1000/timing);
}
getout();
exit(1);
}
getout()
{
XShmDetach(disp,&shminfo);
XDestroyImage(ximage);
shmdt(shminfo.shmaddr);
shmctl(shminfo.shmid, IPC_RMID, 0);
XDestroyWindow(disp,window);
XCloseDisplay(disp);
}
int GetTimeInMs()
{
struct timeval tp;
gettimeofday(&tp,0);
return(tp.tv_sec*1000)+(tp.tv_usec/1000);
}
putsquare(int x, int y,char colourmap[])
{
int i,j,k,l;
for(k=y,l=x,i=0;i<32;i++,k=y+i)
for(j=0;j<32;j++,l=x+j) colourmap[(k*WIDTH)+l]=j+25;
}
---------------------------------8<------------------------------------------
Jon.
--
Email: j...@neurodne.demon.co.uk
Linux/X11 3D programmer
It compiles on HPUX 10.10 with the following line:
cc -g -D_XOPEN_SOURCE_EXTENDED -Aa z.c -lm -lX11 -lXext
It works until the block reaches the top of the screen then core dumps:
153: }
154:
155: putsquare(int x, int y,char colourmap[])
> 156: {
157: int i,j,k,l;
158: for(k=y,l=x,i=0;i<32;i++,k=y+i)
159: for(j=0;j<32;j++,l=x+j)
colourmap[(k*WIDTH)+l]=j+2
160: }
Backtrace:
0 putsquare (x = 239, y = -1, colourmap = 0xc196e000) [z.c: 156]
1 main () [z.c: 122]
I think the debugger's lying about the line number. Change line 159 to:
for(j=0;j<32;j++,l=x+j) if (k >= 0) colourmap[(k*WIDTH)+l]=j+2
and it works.
--
Tim Shaw NetManSys, 30 Chemin du Vieux Chene, 38240 Meylan France
mailto:t...@netmansys.fr http://www.netmansys.fr Tel: +33 76 90 98 22
: It compiles on HPUX 10.10 with the following line:
: cc -g -D_XOPEN_SOURCE_EXTENDED -Aa z.c -lm -lX11 -lXext
: It works until the block reaches the top of the screen then core dumps:
Whoops!
: 153: }
: 154:
: 155: putsquare(int x, int y,char colourmap[])
: > 156: {
: 157: int i,j,k,l;
: 158: for(k=y,l=x,i=0;i<32;i++,k=y+i)
: 159: for(j=0;j<32;j++,l=x+j)
: colourmap[(k*WIDTH)+l]=j+2
: 160: }
: Backtrace:
: 0 putsquare (x = 239, y = -1, colourmap = 0xc196e000) [z.c: 156]
: 1 main () [z.c: 122]
: I think the debugger's lying about the line number. Change line 159 to:
: for(j=0;j<32;j++,l=x+j) if (k >= 0) colourmap[(k*WIDTH)+l]=j+2
: and it works.
Yep, nice one Tim. Also if you change lines 115 and 116 to:
if(x<=0) i=1;
if(y<=0) j=1;
This should keep x and y >=0 and should stop the writes going outside the
shared buffer boundary. This should have the same effect as your post.
Cheers,