2
* Test the GLFBDev interface. Only tested with radeonfb driver!!!!
4
* Written by Brian Paul
16
#include <sys/ioctl.h>
18
#include <sys/types.h>
23
#include <GL/glfbdev.h>
26
#define DEFAULT_DEPTH 8
28
static struct fb_fix_screeninfo FixedInfo;
29
static struct fb_var_screeninfo VarInfo, OrigVarInfo;
30
static int DesiredDepth = 0;
31
static int OriginalVT = -1;
32
static int ConsoleFD = -1;
33
static int FrameBufferFD = -1;
34
static caddr_t FrameBuffer = (caddr_t) -1;
35
static caddr_t MMIOAddress = (caddr_t) -1;
39
print_fixed_info(const struct fb_fix_screeninfo *fixed, const char *s)
41
static const char *visuals[] = {
42
"MONO01", "MONO10", "TRUECOLOR", "PSEUDOCOLOR",
43
"DIRECTCOLOR", "STATIC_PSEUDOCOLOR"
46
printf("%s info -----------------------\n", s);
47
printf("id = %16s\n", fixed->id);
48
printf("smem_start = 0x%lx\n", fixed->smem_start);
49
printf("smem_len = %d (0x%x)\n", fixed->smem_len, fixed->smem_len);
50
printf("type = 0x%x\n", fixed->type);
51
printf("type_aux = 0x%x\n", fixed->type_aux);
52
printf("visual = 0x%x (%s)\n", fixed->visual, visuals[fixed->visual]);
53
printf("xpanstep = %d\n", fixed->xpanstep);
54
printf("ypanstep = %d\n", fixed->ypanstep);
55
printf("ywrapstep = %d\n", fixed->ywrapstep);
56
printf("line_length = %d\n", fixed->line_length);
57
printf("mmio_start = 0x%lx\n", fixed->mmio_start);
58
printf("mmio_len = %d (0x%x)\n", fixed->mmio_len, fixed->mmio_len);
59
printf("accel = 0x%x\n", fixed->accel);
64
print_var_info(const struct fb_var_screeninfo *var, const char *s)
66
printf("%s info -----------------------\n", s);
67
printf("xres = %d\n", var->xres);
68
printf("yres = %d\n", var->yres);
69
printf("xres_virtual = %d\n", var->xres_virtual);
70
printf("yres_virtual = %d\n", var->yres_virtual);
71
printf("xoffset = %d\n", var->xoffset);
72
printf("yoffset = %d\n", var->yoffset);
73
printf("bits_per_pixel = %d\n", var->bits_per_pixel);
74
printf("grayscale = %d\n", var->grayscale);
76
printf("red.offset = %d length = %d msb_right = %d\n",
77
var->red.offset, var->red.length, var->red.msb_right);
78
printf("green.offset = %d length = %d msb_right = %d\n",
79
var->green.offset, var->green.length, var->green.msb_right);
80
printf("blue.offset = %d length = %d msb_right = %d\n",
81
var->blue.offset, var->blue.length, var->blue.msb_right);
82
printf("transp.offset = %d length = %d msb_right = %d\n",
83
var->transp.offset, var->transp.length, var->transp.msb_right);
85
printf("nonstd = %d\n", var->nonstd);
86
printf("activate = %d\n", var->activate);
87
printf("height = %d mm\n", var->height);
88
printf("width = %d mm\n", var->width);
89
printf("accel_flags = 0x%x\n", var->accel_flags);
90
printf("pixclock = %d\n", var->pixclock);
91
printf("left_margin = %d\n", var->left_margin);
92
printf("right_margin = %d\n", var->right_margin);
93
printf("upper_margin = %d\n", var->upper_margin);
94
printf("lower_margin = %d\n", var->lower_margin);
95
printf("hsync_len = %d\n", var->hsync_len);
96
printf("vsync_len = %d\n", var->vsync_len);
97
printf("sync = %d\n", var->sync);
98
printf("vmode = %d\n", var->vmode);
103
signal_handler(int signumber)
105
signal(signumber, SIG_IGN); /* prevent recursion! */
106
fprintf(stderr, "error: got signal %d (exiting)\n", signumber);
112
initialize_fbdev( void )
115
int fd, vtnumber, ttyfd;
121
fprintf(stderr, "error: you need to be root\n");
126
/* open the framebuffer device */
127
FrameBufferFD = open("/dev/fb0", O_RDWR);
128
if (FrameBufferFD < 0) {
129
fprintf(stderr, "Error opening /dev/fb0: %s\n", strerror(errno));
134
/* open /dev/tty0 and get the vt number */
135
if ((fd = open("/dev/tty0", O_WRONLY, 0)) < 0) {
136
fprintf(stderr, "error opening /dev/tty0\n");
139
if (ioctl(fd, VT_OPENQRY, &vtnumber) < 0 || vtnumber < 0) {
140
fprintf(stderr, "error: couldn't get a free vt\n");
145
/* open the console tty */
146
sprintf(ttystr, "/dev/tty%d", vtnumber); /* /dev/tty1-64 */
147
ConsoleFD = open(ttystr, O_RDWR | O_NDELAY, 0);
149
fprintf(stderr, "error couldn't open console fd\n");
153
/* save current vt number */
156
if (ioctl(ConsoleFD, VT_GETSTATE, &vts) == 0)
157
OriginalVT = vts.v_active;
160
/* disconnect from controlling tty */
161
ttyfd = open("/dev/tty", O_RDWR);
163
ioctl(ttyfd, TIOCNOTTY, 0);
167
/* some magic to restore the vt when we exit */
170
if (ioctl(ConsoleFD, VT_ACTIVATE, vtnumber) != 0)
171
printf("ioctl VT_ACTIVATE: %s\n", strerror(errno));
172
if (ioctl(ConsoleFD, VT_WAITACTIVE, vtnumber) != 0)
173
printf("ioctl VT_WAITACTIVE: %s\n", strerror(errno));
175
if (ioctl(ConsoleFD, VT_GETMODE, &vt) < 0) {
176
fprintf(stderr, "error: ioctl VT_GETMODE: %s\n", strerror(errno));
180
vt.mode = VT_PROCESS;
183
if (ioctl(ConsoleFD, VT_SETMODE, &vt) < 0) {
184
fprintf(stderr, "error: ioctl(VT_SETMODE) failed: %s\n",
190
/* go into graphics mode */
191
if (ioctl(ConsoleFD, KDSETMODE, KD_GRAPHICS) < 0) {
192
fprintf(stderr, "error: ioctl(KDSETMODE, KD_GRAPHICS) failed: %s\n",
199
/* open the framebuffer device */
200
FrameBufferFD = open("/dev/fb0", O_RDWR);
201
if (FrameBufferFD < 0) {
202
fprintf(stderr, "Error opening /dev/fb0: %s\n", strerror(errno));
207
/* Get the fixed screen info */
208
if (ioctl(FrameBufferFD, FBIOGET_FSCREENINFO, &FixedInfo)) {
209
fprintf(stderr, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
214
print_fixed_info(&FixedInfo, "Fixed");
217
/* get the variable screen info */
218
if (ioctl(FrameBufferFD, FBIOGET_VSCREENINFO, &OrigVarInfo)) {
219
fprintf(stderr, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
224
print_var_info(&OrigVarInfo, "Orig Var");
226
/* operate on a copy */
227
VarInfo = OrigVarInfo;
229
/* set the depth, resolution, etc */
232
VarInfo.bits_per_pixel = DesiredDepth;
234
if (VarInfo.bits_per_pixel == 16) {
235
VarInfo.red.offset = 11;
236
VarInfo.green.offset = 5;
237
VarInfo.blue.offset = 0;
238
VarInfo.red.length = 5;
239
VarInfo.green.length = 6;
240
VarInfo.blue.length = 5;
241
VarInfo.transp.offset = 0;
242
VarInfo.transp.length = 0;
244
else if (VarInfo.bits_per_pixel == 32) {
245
VarInfo.red.offset = 16;
246
VarInfo.green.offset = 8;
247
VarInfo.blue.offset = 0;
248
VarInfo.transp.offset = 24;
249
VarInfo.red.length = 8;
250
VarInfo.green.length = 8;
251
VarInfo.blue.length = 8;
252
VarInfo.transp.length = 8;
254
/* timing values taken from /etc/fb.modes (1280x1024 @ 75Hz) */
255
VarInfo.xres_virtual = VarInfo.xres = 1280;
256
VarInfo.yres_virtual = VarInfo.yres = 1024;
257
VarInfo.pixclock = 7408;
258
VarInfo.left_margin = 248;
259
VarInfo.right_margin = 16;
260
VarInfo.upper_margin = 38;
261
VarInfo.lower_margin = 1;
262
VarInfo.hsync_len = 144;
263
VarInfo.vsync_len = 3;
268
VarInfo.vmode &= ~FB_VMODE_YWRAP; /* turn off scrolling */
270
/* set new variable screen info */
271
if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &VarInfo)) {
272
fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
277
print_var_info(&VarInfo, "New Var");
279
if (FixedInfo.visual != FB_VISUAL_TRUECOLOR &&
280
FixedInfo.visual != FB_VISUAL_DIRECTCOLOR) {
281
fprintf(stderr, "non-TRUE/DIRECT-COLOR visuals (0x%x) not supported by this demo.\n", FixedInfo.visual);
285
/* initialize colormap */
286
if (FixedInfo.visual == FB_VISUAL_DIRECTCOLOR) {
288
unsigned short red[256], green[256], blue[256];
291
/* we're assuming 256 entries here */
292
printf("initializing directcolor colormap\n");
299
for (i = 0; i < cmap.len; i++) {
300
red[i] = green[i] = blue[i] = (i << 8) | i;
302
if (ioctl(FrameBufferFD, FBIOPUTCMAP, (void *) &cmap) < 0) {
303
fprintf(stderr, "ioctl(FBIOPUTCMAP) failed [%d]\n", i);
308
* fbdev says the frame buffer is at offset zero, and the mmio region
309
* is immediately after.
312
/* mmap the framebuffer into our address space */
313
FrameBuffer = (caddr_t) mmap(0, /* start */
314
FixedInfo.smem_len, /* bytes */
315
PROT_READ | PROT_WRITE, /* prot */
316
MAP_SHARED, /* flags */
317
FrameBufferFD, /* fd */
319
if (FrameBuffer == (caddr_t) - 1) {
320
fprintf(stderr, "error: unable to mmap framebuffer: %s\n",
324
printf("FrameBuffer = %p\n", FrameBuffer);
327
/* mmap the MMIO region into our address space */
328
MMIOAddress = (caddr_t) mmap(0, /* start */
329
FixedInfo.mmio_len, /* bytes */
330
PROT_READ | PROT_WRITE, /* prot */
331
MAP_SHARED, /* flags */
332
FrameBufferFD, /* fd */
333
FixedInfo.smem_len /* offset */);
334
if (MMIOAddress == (caddr_t) - 1) {
335
fprintf(stderr, "error: unable to mmap mmio region: %s\n",
338
printf("MMIOAddress = %p\n", MMIOAddress);
340
/* try out some simple MMIO register reads */
343
typedef unsigned int CARD32;
344
typedef unsigned char CARD8;
345
#define RADEON_CONFIG_MEMSIZE 0x00f8
346
#define RADEON_MEM_SDRAM_MODE_REG 0x0158
347
#define MMIO_IN32(base, offset) \
348
*(volatile CARD32 *)(void *)(((CARD8*)(base)) + (offset))
349
#define INREG(addr) MMIO_IN32(MMIOAddress, addr)
351
const char *typeStr[] = {"SDR", "DDR", "64-bit SDR"};
352
sz = INREG(RADEON_CONFIG_MEMSIZE);
353
type = INREG(RADEON_MEM_SDRAM_MODE_REG);
354
printf("RADEON_CONFIG_MEMSIZE = %d (%d MB)\n", sz, sz / 1024 / 1024);
355
printf("RADEON_MEM_SDRAM_MODE_REG >> 30 = %d (%s)\n",
356
type >> 30, typeStr[type>>30]);
364
shutdown_fbdev( void )
368
printf("cleaning up...\n");
369
/* restore original variable screen info */
370
if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &OrigVarInfo)) {
371
fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
376
munmap(MMIOAddress, FixedInfo.mmio_len);
377
munmap(FrameBuffer, FixedInfo.smem_len);
378
close(FrameBufferFD);
380
/* restore text mode */
381
ioctl(ConsoleFD, KDSETMODE, KD_TEXT);
384
if (ioctl(ConsoleFD, VT_GETMODE, &VT) != -1) {
386
ioctl(ConsoleFD, VT_SETMODE, &VT);
389
/* restore original vt */
390
if (OriginalVT >= 0) {
391
ioctl(ConsoleFD, VT_ACTIVATE, OriginalVT);
399
/* Borrowed from GLUT */
401
doughnut(GLfloat r, GLfloat R, GLint nsides, GLint rings)
404
GLfloat theta, phi, theta1;
405
GLfloat cosTheta, sinTheta;
406
GLfloat cosTheta1, sinTheta1;
407
GLfloat ringDelta, sideDelta;
409
ringDelta = 2.0 * M_PI / rings;
410
sideDelta = 2.0 * M_PI / nsides;
415
for (i = rings - 1; i >= 0; i--) {
416
theta1 = theta + ringDelta;
417
cosTheta1 = cos(theta1);
418
sinTheta1 = sin(theta1);
419
glBegin(GL_QUAD_STRIP);
421
for (j = nsides; j >= 0; j--) {
422
GLfloat cosPhi, sinPhi, dist;
427
dist = R + r * cosPhi;
429
glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
430
glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
431
glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
432
glVertex3f(cosTheta * dist, -sinTheta * dist, r * sinPhi);
436
cosTheta = cosTheta1;
437
sinTheta = sinTheta1;
445
static const int attribs[] = {
446
GLFBDEV_DOUBLE_BUFFER,
447
GLFBDEV_DEPTH_SIZE, 16,
450
GLFBDevContextPtr ctx;
451
GLFBDevBufferPtr buf;
452
GLFBDevVisualPtr vis;
453
int bytes, r, g, b, a;
456
printf("GLFBDEV_VENDOR = %s\n", glFBDevGetString(GLFBDEV_VENDOR));
457
printf("GLFBDEV_VERSION = %s\n", glFBDevGetString(GLFBDEV_VERSION));
459
/* framebuffer size */
460
bytes = VarInfo.xres_virtual * VarInfo.yres_virtual * VarInfo.bits_per_pixel / 8;
462
vis = glFBDevCreateVisual( &FixedInfo, &VarInfo, attribs );
465
buf = glFBDevCreateBuffer( &FixedInfo, &VarInfo, vis, FrameBuffer, NULL, bytes );
468
ctx = glFBDevCreateContext( vis, NULL );
471
b = glFBDevMakeCurrent( ctx, buf, buf );
474
/*printf("GL_EXTENSIONS: %s\n", glGetString(GL_EXTENSIONS));*/
475
glGetIntegerv(GL_RED_BITS, &r);
476
glGetIntegerv(GL_GREEN_BITS, &g);
477
glGetIntegerv(GL_BLUE_BITS, &b);
478
glGetIntegerv(GL_ALPHA_BITS, &a);
479
printf("RED_BITS=%d GREEN_BITS=%d BLUE_BITS=%d ALPHA_BITS=%d\n",
482
glClearColor(0.5, 0.5, 1.0, 0);
483
glMatrixMode(GL_PROJECTION);
485
glFrustum(-1, 1, -1, 1, 2, 30);
486
glMatrixMode(GL_MODELVIEW);
488
glTranslatef(0, 0, -15);
489
glViewport(0, 0, VarInfo.xres_virtual, VarInfo.yres_virtual);
490
glEnable(GL_LIGHTING);
492
glEnable(GL_DEPTH_TEST);
494
for (ang = 0; ang <= 180; ang += 15) {
495
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
497
glRotatef(ang, 1, 0, 0);
498
doughnut(1, 3, 40, 20);
500
glFBDevSwapBuffers(buf);
504
b = glFBDevMakeCurrent( NULL, NULL, NULL);
507
glFBDevDestroyContext(ctx);
508
glFBDevDestroyBuffer(buf);
509
glFBDevDestroyVisual(vis);
514
main( int argc, char *argv[] )
516
signal(SIGUSR1, signal_handler); /* exit if someone tries a vt switch */
517
signal(SIGSEGV, signal_handler); /* catch segfaults */