3 * Test the GLFBDev interface. Only tested with radeonfb driver!!!!
15 #include <sys/ioctl.h>
17 #include <sys/types.h>
22 #include "GL/glfbdev.h"
24 #define DEFAULT_DEPTH 8
26 static struct fb_fix_screeninfo FixedInfo
;
27 static struct fb_var_screeninfo VarInfo
, OrigVarInfo
;
28 static int DesiredDepth
= 0;
29 static int OriginalVT
= -1;
30 static int ConsoleFD
= -1;
31 static int FrameBufferFD
= -1;
32 static caddr_t FrameBuffer
= (caddr_t
) -1;
33 static caddr_t MMIOAddress
= (caddr_t
) -1;
37 print_fixed_info(const struct fb_fix_screeninfo
*fixed
, const char *s
)
39 static const char *visuals
[] = {
40 "MONO01", "MONO10", "TRUECOLOR", "PSEUDOCOLOR",
41 "DIRECTCOLOR", "STATIC_PSEUDOCOLOR"
44 printf("%s info -----------------------\n", s
);
45 printf("id = %16s\n", fixed
->id
);
46 printf("smem_start = 0x%x\n", fixed
->smem_start
);
47 printf("smem_len = %d (0x%x)\n", fixed
->smem_len
, fixed
->smem_len
);
48 printf("type = 0x%x\n", fixed
->type
);
49 printf("type_aux = 0x%x\n", fixed
->type_aux
);
50 printf("visual = 0x%x (%s)\n", fixed
->visual
, visuals
[fixed
->visual
]);
51 printf("xpanstep = %d\n", fixed
->xpanstep
);
52 printf("ypanstep = %d\n", fixed
->ypanstep
);
53 printf("ywrapstep = %d\n", fixed
->ywrapstep
);
54 printf("line_length = %d\n", fixed
->line_length
);
55 printf("mmio_start = 0x%x\n", fixed
->mmio_start
);
56 printf("mmio_len = %d (0x%x)\n", fixed
->mmio_len
, fixed
->mmio_len
);
57 printf("accel = 0x%x\n", fixed
->accel
);
62 print_var_info(const struct fb_var_screeninfo
*var
, const char *s
)
64 printf("%s info -----------------------\n", s
);
65 printf("xres = %d\n", var
->xres
);
66 printf("yres = %d\n", var
->yres
);
67 printf("xres_virtual = %d\n", var
->xres_virtual
);
68 printf("yres_virtual = %d\n", var
->yres_virtual
);
69 printf("xoffset = %d\n", var
->xoffset
);
70 printf("yoffset = %d\n", var
->yoffset
);
71 printf("bits_per_pixel = %d\n", var
->bits_per_pixel
);
72 printf("grayscale = %d\n", var
->grayscale
);
74 printf("red.offset = %d length = %d msb_right = %d\n",
75 var
->red
.offset
, var
->red
.length
, var
->red
.msb_right
);
76 printf("green.offset = %d length = %d msb_right = %d\n",
77 var
->green
.offset
, var
->green
.length
, var
->green
.msb_right
);
78 printf("blue.offset = %d length = %d msb_right = %d\n",
79 var
->blue
.offset
, var
->blue
.length
, var
->blue
.msb_right
);
80 printf("transp.offset = %d length = %d msb_right = %d\n",
81 var
->transp
.offset
, var
->transp
.length
, var
->transp
.msb_right
);
83 printf("nonstd = %d\n", var
->nonstd
);
84 printf("activate = %d\n", var
->activate
);
85 printf("height = %d mm\n", var
->height
);
86 printf("width = %d mm\n", var
->width
);
87 printf("accel_flags = 0x%x\n", var
->accel_flags
);
88 printf("pixclock = %d\n", var
->pixclock
);
89 printf("left_margin = %d\n", var
->left_margin
);
90 printf("right_margin = %d\n", var
->right_margin
);
91 printf("upper_margin = %d\n", var
->upper_margin
);
92 printf("lower_margin = %d\n", var
->lower_margin
);
93 printf("hsync_len = %d\n", var
->hsync_len
);
94 printf("vsync_len = %d\n", var
->vsync_len
);
95 printf("sync = %d\n", var
->sync
);
96 printf("vmode = %d\n", var
->vmode
);
101 signal_handler(int signumber
)
103 signal(signumber
, SIG_IGN
); /* prevent recursion! */
104 fprintf(stderr
, "error: got signal %d (exiting)\n", signumber
);
110 initialize_fbdev( void )
113 int fd
, vtnumber
, ttyfd
;
117 fprintf(stderr
, "error: you need to be root\n");
122 /* open the framebuffer device */
123 FrameBufferFD
= open("/dev/fb0", O_RDWR
);
124 if (FrameBufferFD
< 0) {
125 fprintf(stderr
, "Error opening /dev/fb0: %s\n", strerror(errno
));
130 /* open /dev/tty0 and get the vt number */
131 if ((fd
= open("/dev/tty0", O_WRONLY
, 0)) < 0) {
132 fprintf(stderr
, "error opening /dev/tty0\n");
135 if (ioctl(fd
, VT_OPENQRY
, &vtnumber
) < 0 || vtnumber
< 0) {
136 fprintf(stderr
, "error: couldn't get a free vt\n");
141 /* open the console tty */
142 sprintf(ttystr
, "/dev/tty%d", vtnumber
); /* /dev/tty1-64 */
143 ConsoleFD
= open(ttystr
, O_RDWR
| O_NDELAY
, 0);
145 fprintf(stderr
, "error couldn't open console fd\n");
149 /* save current vt number */
152 if (ioctl(ConsoleFD
, VT_GETSTATE
, &vts
) == 0)
153 OriginalVT
= vts
.v_active
;
156 /* disconnect from controlling tty */
157 ttyfd
= open("/dev/tty", O_RDWR
);
159 ioctl(ttyfd
, TIOCNOTTY
, 0);
163 /* some magic to restore the vt when we exit */
166 if (ioctl(ConsoleFD
, VT_ACTIVATE
, vtnumber
) != 0)
167 printf("ioctl VT_ACTIVATE: %s\n", strerror(errno
));
168 if (ioctl(ConsoleFD
, VT_WAITACTIVE
, vtnumber
) != 0)
169 printf("ioctl VT_WAITACTIVE: %s\n", strerror(errno
));
171 if (ioctl(ConsoleFD
, VT_GETMODE
, &vt
) < 0) {
172 fprintf(stderr
, "error: ioctl VT_GETMODE: %s\n", strerror(errno
));
176 vt
.mode
= VT_PROCESS
;
179 if (ioctl(ConsoleFD
, VT_SETMODE
, &vt
) < 0) {
180 fprintf(stderr
, "error: ioctl(VT_SETMODE) failed: %s\n",
186 /* go into graphics mode */
187 if (ioctl(ConsoleFD
, KDSETMODE
, KD_GRAPHICS
) < 0) {
188 fprintf(stderr
, "error: ioctl(KDSETMODE, KD_GRAPHICS) failed: %s\n",
195 /* open the framebuffer device */
196 FrameBufferFD
= open("/dev/fb0", O_RDWR
);
197 if (FrameBufferFD
< 0) {
198 fprintf(stderr
, "Error opening /dev/fb0: %s\n", strerror(errno
));
203 /* Get the fixed screen info */
204 if (ioctl(FrameBufferFD
, FBIOGET_FSCREENINFO
, &FixedInfo
)) {
205 fprintf(stderr
, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
210 print_fixed_info(&FixedInfo
, "Fixed");
213 /* get the variable screen info */
214 if (ioctl(FrameBufferFD
, FBIOGET_VSCREENINFO
, &OrigVarInfo
)) {
215 fprintf(stderr
, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
220 print_var_info(&OrigVarInfo
, "Orig Var");
222 /* operate on a copy */
223 VarInfo
= OrigVarInfo
;
225 /* set the depth, resolution, etc */
228 VarInfo
.bits_per_pixel
= DesiredDepth
;
230 if (VarInfo
.bits_per_pixel
== 16) {
231 VarInfo
.red
.offset
= 11;
232 VarInfo
.green
.offset
= 5;
233 VarInfo
.blue
.offset
= 0;
234 VarInfo
.red
.length
= 5;
235 VarInfo
.green
.length
= 6;
236 VarInfo
.blue
.length
= 5;
237 VarInfo
.transp
.offset
= 0;
238 VarInfo
.transp
.length
= 0;
240 else if (VarInfo
.bits_per_pixel
== 32) {
241 VarInfo
.red
.offset
= 16;
242 VarInfo
.green
.offset
= 8;
243 VarInfo
.blue
.offset
= 0;
244 VarInfo
.transp
.offset
= 24;
245 VarInfo
.red
.length
= 8;
246 VarInfo
.green
.length
= 8;
247 VarInfo
.blue
.length
= 8;
248 VarInfo
.transp
.length
= 8;
250 /* timing values taken from /etc/fb.modes (1280x1024 @ 75Hz) */
251 VarInfo
.xres_virtual
= VarInfo
.xres
= 1280;
252 VarInfo
.yres_virtual
= VarInfo
.yres
= 1024;
253 VarInfo
.pixclock
= 7408;
254 VarInfo
.left_margin
= 248;
255 VarInfo
.right_margin
= 16;
256 VarInfo
.upper_margin
= 38;
257 VarInfo
.lower_margin
= 1;
258 VarInfo
.hsync_len
= 144;
259 VarInfo
.vsync_len
= 3;
264 VarInfo
.vmode
&= ~FB_VMODE_YWRAP
; /* turn off scrolling */
266 /* set new variable screen info */
267 if (ioctl(FrameBufferFD
, FBIOPUT_VSCREENINFO
, &VarInfo
)) {
268 fprintf(stderr
, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
273 print_var_info(&VarInfo
, "New Var");
275 if (FixedInfo
.visual
!= FB_VISUAL_TRUECOLOR
&&
276 FixedInfo
.visual
!= FB_VISUAL_DIRECTCOLOR
) {
277 fprintf(stderr
, "non-TRUE/DIRECT-COLOR visuals (0x%x) not supported by this demo.\n", FixedInfo
.visual
);
281 /* initialize colormap */
282 if (FixedInfo
.visual
== FB_VISUAL_DIRECTCOLOR
) {
284 unsigned short red
[256], green
[256], blue
[256];
287 /* we're assuming 256 entries here */
288 printf("initializing directcolor colormap\n");
295 for (i
= 0; i
< cmap
.len
; i
++) {
296 red
[i
] = green
[i
] = blue
[i
] = (i
<< 8) | i
;
298 if (ioctl(FrameBufferFD
, FBIOPUTCMAP
, (void *) &cmap
) < 0) {
299 fprintf(stderr
, "ioctl(FBIOPUTCMAP) failed [%d]\n", i
);
304 * fbdev says the frame buffer is at offset zero, and the mmio region
305 * is immediately after.
308 /* mmap the framebuffer into our address space */
309 FrameBuffer
= (caddr_t
) mmap(0, /* start */
310 FixedInfo
.smem_len
, /* bytes */
311 PROT_READ
| PROT_WRITE
, /* prot */
312 MAP_SHARED
, /* flags */
313 FrameBufferFD
, /* fd */
315 if (FrameBuffer
== (caddr_t
) - 1) {
316 fprintf(stderr
, "error: unable to mmap framebuffer: %s\n",
320 printf("FrameBuffer = %p\n", FrameBuffer
);
323 /* mmap the MMIO region into our address space */
324 MMIOAddress
= (caddr_t
) mmap(0, /* start */
325 FixedInfo
.mmio_len
, /* bytes */
326 PROT_READ
| PROT_WRITE
, /* prot */
327 MAP_SHARED
, /* flags */
328 FrameBufferFD
, /* fd */
329 FixedInfo
.smem_len
/* offset */);
330 if (MMIOAddress
== (caddr_t
) - 1) {
331 fprintf(stderr
, "error: unable to mmap mmio region: %s\n",
334 printf("MMIOAddress = %p\n", MMIOAddress
);
336 /* try out some simple MMIO register reads */
339 typedef unsigned int CARD32
;
340 typedef unsigned char CARD8
;
341 #define RADEON_CONFIG_MEMSIZE 0x00f8
342 #define RADEON_MEM_SDRAM_MODE_REG 0x0158
343 #define MMIO_IN32(base, offset) \
344 *(volatile CARD32 *)(void *)(((CARD8*)(base)) + (offset))
345 #define INREG(addr) MMIO_IN32(MMIOAddress, addr)
347 const char *typeStr
[] = {"SDR", "DDR", "64-bit SDR"};
348 sz
= INREG(RADEON_CONFIG_MEMSIZE
);
349 type
= INREG(RADEON_MEM_SDRAM_MODE_REG
);
350 printf("RADEON_CONFIG_MEMSIZE = %d (%d MB)\n", sz
, sz
/ 1024 / 1024);
351 printf("RADEON_MEM_SDRAM_MODE_REG >> 30 = %d (%s)\n",
352 type
>> 30, typeStr
[type
>>30]);
360 shutdown_fbdev( void )
364 printf("cleaning up...\n");
365 /* restore original variable screen info */
366 if (ioctl(FrameBufferFD
, FBIOPUT_VSCREENINFO
, &OrigVarInfo
)) {
367 fprintf(stderr
, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
372 munmap(MMIOAddress
, FixedInfo
.mmio_len
);
373 munmap(FrameBuffer
, FixedInfo
.smem_len
);
374 close(FrameBufferFD
);
376 /* restore text mode */
377 ioctl(ConsoleFD
, KDSETMODE
, KD_TEXT
);
380 if (ioctl(ConsoleFD
, VT_GETMODE
, &VT
) != -1) {
382 ioctl(ConsoleFD
, VT_SETMODE
, &VT
);
385 /* restore original vt */
386 if (OriginalVT
>= 0) {
387 ioctl(ConsoleFD
, VT_ACTIVATE
, OriginalVT
);
398 static const int attribs
[] = {
399 GLFBDEV_DOUBLE_BUFFER
,
400 GLFBDEV_DEPTH_SIZE
, 16,
403 GLFBDevContextPtr ctx
;
404 GLFBDevBufferPtr buf
;
405 GLFBDevVisualPtr vis
;
406 int bytes
, r
, g
, b
, a
;
409 printf("GLFBDEV_VENDOR = %s\n", glFBDevGetString(GLFBDEV_VENDOR
));
410 printf("GLFBDEV_VERSION = %s\n", glFBDevGetString(GLFBDEV_VERSION
));
412 /* framebuffer size */
413 bytes
= VarInfo
.xres_virtual
* VarInfo
.yres_virtual
* VarInfo
.bits_per_pixel
/ 8;
415 vis
= glFBDevCreateVisual( &FixedInfo
, &VarInfo
, attribs
);
418 buf
= glFBDevCreateBuffer( &FixedInfo
, &VarInfo
, vis
, FrameBuffer
, NULL
, bytes
);
421 ctx
= glFBDevCreateContext( vis
, NULL
);
424 b
= glFBDevMakeCurrent( ctx
, buf
, buf
);
427 /*printf("GL_EXTENSIONS: %s\n", glGetString(GL_EXTENSIONS));*/
428 glGetIntegerv(GL_RED_BITS
, &r
);
429 glGetIntegerv(GL_GREEN_BITS
, &g
);
430 glGetIntegerv(GL_BLUE_BITS
, &b
);
431 glGetIntegerv(GL_ALPHA_BITS
, &a
);
432 printf("RED_BITS=%d GREEN_BITS=%d BLUE_BITS=%d ALPHA_BITS=%d\n",
435 glClearColor(0.5, 0.5, 1.0, 0);
436 glMatrixMode(GL_PROJECTION
);
438 glFrustum(-1, 1, -1, 1, 2, 30);
439 glMatrixMode(GL_MODELVIEW
);
441 glTranslatef(0, 0, -15);
442 glViewport(0, 0, VarInfo
.xres_virtual
, VarInfo
.yres_virtual
);
443 glEnable(GL_LIGHTING
);
445 glEnable(GL_DEPTH_TEST
);
447 for (ang
= 0; ang
<= 180; ang
+= 15) {
448 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
450 glRotatef(ang
, 1, 0, 0);
451 glutSolidTorus(1, 3, 40, 20);
453 glFBDevSwapBuffers(buf
);
457 b
= glFBDevMakeCurrent( NULL
, NULL
, NULL
);
460 glFBDevDestroyContext(ctx
);
461 glFBDevDestroyBuffer(buf
);
462 glFBDevDestroyVisual(vis
);
467 main( int argc
, char *argv
[] )
469 signal(SIGUSR1
, signal_handler
); /* exit if someone tries a vt switch */
470 signal(SIGSEGV
, signal_handler
); /* catch segfaults */