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 */