Remove CVS keywords.
[mesa.git] / progs / miniglx / glfbdevtest.c
1
2 /*
3 * Test the GLFBDev interface. Only tested with radeonfb driver!!!!
4 */
5
6
7 #include <assert.h>
8 #include <errno.h>
9 #include <signal.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include <sys/ioctl.h>
16 #include <sys/mman.h>
17 #include <sys/types.h>
18 #include <linux/fb.h>
19 #include <linux/kd.h>
20 #include <linux/vt.h>
21 #include <GL/glut.h>
22 #include "GL/glfbdev.h"
23
24 #define DEFAULT_DEPTH 8
25
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;
34
35
36 static void
37 print_fixed_info(const struct fb_fix_screeninfo *fixed, const char *s)
38 {
39 static const char *visuals[] = {
40 "MONO01", "MONO10", "TRUECOLOR", "PSEUDOCOLOR",
41 "DIRECTCOLOR", "STATIC_PSEUDOCOLOR"
42 };
43
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);
58 }
59
60
61 static void
62 print_var_info(const struct fb_var_screeninfo *var, const char *s)
63 {
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);
73
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);
82
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);
97 }
98
99
100 static void
101 signal_handler(int signumber)
102 {
103 signal(signumber, SIG_IGN); /* prevent recursion! */
104 fprintf(stderr, "error: got signal %d (exiting)\n", signumber);
105 exit(1);
106 }
107
108
109 static void
110 initialize_fbdev( void )
111 {
112 char ttystr[1000];
113 int fd, vtnumber, ttyfd;
114 int sz;
115
116 if (geteuid()) {
117 fprintf(stderr, "error: you need to be root\n");
118 exit(1);
119 }
120
121 #if 1
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));
126 exit(1);
127 }
128 #endif
129
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");
133 exit(1);
134 }
135 if (ioctl(fd, VT_OPENQRY, &vtnumber) < 0 || vtnumber < 0) {
136 fprintf(stderr, "error: couldn't get a free vt\n");
137 exit(1);
138 }
139 close(fd);
140
141 /* open the console tty */
142 sprintf(ttystr, "/dev/tty%d", vtnumber); /* /dev/tty1-64 */
143 ConsoleFD = open(ttystr, O_RDWR | O_NDELAY, 0);
144 if (ConsoleFD < 0) {
145 fprintf(stderr, "error couldn't open console fd\n");
146 exit(1);
147 }
148
149 /* save current vt number */
150 {
151 struct vt_stat vts;
152 if (ioctl(ConsoleFD, VT_GETSTATE, &vts) == 0)
153 OriginalVT = vts.v_active;
154 }
155
156 /* disconnect from controlling tty */
157 ttyfd = open("/dev/tty", O_RDWR);
158 if (ttyfd >= 0) {
159 ioctl(ttyfd, TIOCNOTTY, 0);
160 close(ttyfd);
161 }
162
163 /* some magic to restore the vt when we exit */
164 {
165 struct vt_mode vt;
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));
170
171 if (ioctl(ConsoleFD, VT_GETMODE, &vt) < 0) {
172 fprintf(stderr, "error: ioctl VT_GETMODE: %s\n", strerror(errno));
173 exit(1);
174 }
175
176 vt.mode = VT_PROCESS;
177 vt.relsig = SIGUSR1;
178 vt.acqsig = SIGUSR1;
179 if (ioctl(ConsoleFD, VT_SETMODE, &vt) < 0) {
180 fprintf(stderr, "error: ioctl(VT_SETMODE) failed: %s\n",
181 strerror(errno));
182 exit(1);
183 }
184 }
185
186 /* go into graphics mode */
187 if (ioctl(ConsoleFD, KDSETMODE, KD_GRAPHICS) < 0) {
188 fprintf(stderr, "error: ioctl(KDSETMODE, KD_GRAPHICS) failed: %s\n",
189 strerror(errno));
190 exit(1);
191 }
192
193
194 #if 0
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));
199 exit(1);
200 }
201 #endif
202
203 /* Get the fixed screen info */
204 if (ioctl(FrameBufferFD, FBIOGET_FSCREENINFO, &FixedInfo)) {
205 fprintf(stderr, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
206 strerror(errno));
207 exit(1);
208 }
209
210 print_fixed_info(&FixedInfo, "Fixed");
211
212
213 /* get the variable screen info */
214 if (ioctl(FrameBufferFD, FBIOGET_VSCREENINFO, &OrigVarInfo)) {
215 fprintf(stderr, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
216 strerror(errno));
217 exit(1);
218 }
219
220 print_var_info(&OrigVarInfo, "Orig Var");
221
222 /* operate on a copy */
223 VarInfo = OrigVarInfo;
224
225 /* set the depth, resolution, etc */
226 DesiredDepth = 32;
227 if (DesiredDepth)
228 VarInfo.bits_per_pixel = DesiredDepth;
229
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;
239 }
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;
249 }
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;
260
261 VarInfo.xoffset = 0;
262 VarInfo.yoffset = 0;
263 VarInfo.nonstd = 0;
264 VarInfo.vmode &= ~FB_VMODE_YWRAP; /* turn off scrolling */
265
266 /* set new variable screen info */
267 if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &VarInfo)) {
268 fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
269 strerror(errno));
270 exit(1);
271 }
272
273 print_var_info(&VarInfo, "New Var");
274
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);
278 exit(1);
279 }
280
281 /* initialize colormap */
282 if (FixedInfo.visual == FB_VISUAL_DIRECTCOLOR) {
283 struct fb_cmap cmap;
284 unsigned short red[256], green[256], blue[256];
285 int i;
286
287 /* we're assuming 256 entries here */
288 printf("initializing directcolor colormap\n");
289 cmap.start = 0;
290 cmap.len = 256;
291 cmap.red = red;
292 cmap.green = green;
293 cmap.blue = blue;
294 cmap.transp = NULL;
295 for (i = 0; i < cmap.len; i++) {
296 red[i] = green[i] = blue[i] = (i << 8) | i;
297 }
298 if (ioctl(FrameBufferFD, FBIOPUTCMAP, (void *) &cmap) < 0) {
299 fprintf(stderr, "ioctl(FBIOPUTCMAP) failed [%d]\n", i);
300 }
301 }
302
303 /*
304 * fbdev says the frame buffer is at offset zero, and the mmio region
305 * is immediately after.
306 */
307
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 */
314 0 /* offset */);
315 if (FrameBuffer == (caddr_t) - 1) {
316 fprintf(stderr, "error: unable to mmap framebuffer: %s\n",
317 strerror(errno));
318 exit(1);
319 }
320 printf("FrameBuffer = %p\n", FrameBuffer);
321
322 #if 1
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",
332 strerror(errno));
333 }
334 printf("MMIOAddress = %p\n", MMIOAddress);
335
336 /* try out some simple MMIO register reads */
337 if (1)
338 {
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)
346 int sz, type;
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]);
353 }
354 #endif
355
356 }
357
358
359 static void
360 shutdown_fbdev( void )
361 {
362 struct vt_mode VT;
363
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",
368 strerror(errno));
369 exit(1);
370 }
371
372 munmap(MMIOAddress, FixedInfo.mmio_len);
373 munmap(FrameBuffer, FixedInfo.smem_len);
374 close(FrameBufferFD);
375
376 /* restore text mode */
377 ioctl(ConsoleFD, KDSETMODE, KD_TEXT);
378
379 /* set vt */
380 if (ioctl(ConsoleFD, VT_GETMODE, &VT) != -1) {
381 VT.mode = VT_AUTO;
382 ioctl(ConsoleFD, VT_SETMODE, &VT);
383 }
384
385 /* restore original vt */
386 if (OriginalVT >= 0) {
387 ioctl(ConsoleFD, VT_ACTIVATE, OriginalVT);
388 OriginalVT = -1;
389 }
390
391 close(ConsoleFD);
392 }
393
394
395 static void
396 gltest( void )
397 {
398 static const int attribs[] = {
399 GLFBDEV_DOUBLE_BUFFER,
400 GLFBDEV_DEPTH_SIZE, 16,
401 GLFBDEV_NONE
402 };
403 GLFBDevContextPtr ctx;
404 GLFBDevBufferPtr buf;
405 GLFBDevVisualPtr vis;
406 int bytes, r, g, b, a;
407 float ang;
408
409 printf("GLFBDEV_VENDOR = %s\n", glFBDevGetString(GLFBDEV_VENDOR));
410 printf("GLFBDEV_VERSION = %s\n", glFBDevGetString(GLFBDEV_VERSION));
411
412 /* framebuffer size */
413 bytes = VarInfo.xres_virtual * VarInfo.yres_virtual * VarInfo.bits_per_pixel / 8;
414
415 vis = glFBDevCreateVisual( &FixedInfo, &VarInfo, attribs );
416 assert(vis);
417
418 buf = glFBDevCreateBuffer( &FixedInfo, &VarInfo, vis, FrameBuffer, NULL, bytes );
419 assert(buf);
420
421 ctx = glFBDevCreateContext( vis, NULL );
422 assert(buf);
423
424 b = glFBDevMakeCurrent( ctx, buf, buf );
425 assert(b);
426
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",
433 r, g, b, a);
434
435 glClearColor(0.5, 0.5, 1.0, 0);
436 glMatrixMode(GL_PROJECTION);
437 glLoadIdentity();
438 glFrustum(-1, 1, -1, 1, 2, 30);
439 glMatrixMode(GL_MODELVIEW);
440 glLoadIdentity();
441 glTranslatef(0, 0, -15);
442 glViewport(0, 0, VarInfo.xres_virtual, VarInfo.yres_virtual);
443 glEnable(GL_LIGHTING);
444 glEnable(GL_LIGHT0);
445 glEnable(GL_DEPTH_TEST);
446
447 for (ang = 0; ang <= 180; ang += 15) {
448 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
449 glPushMatrix();
450 glRotatef(ang, 1, 0, 0);
451 glutSolidTorus(1, 3, 40, 20);
452 glPopMatrix();
453 glFBDevSwapBuffers(buf);
454 }
455
456 /* clean up */
457 b = glFBDevMakeCurrent( NULL, NULL, NULL);
458 assert(b);
459
460 glFBDevDestroyContext(ctx);
461 glFBDevDestroyBuffer(buf);
462 glFBDevDestroyVisual(vis);
463 }
464
465
466 int
467 main( int argc, char *argv[] )
468 {
469 signal(SIGUSR1, signal_handler); /* exit if someone tries a vt switch */
470 signal(SIGSEGV, signal_handler); /* catch segfaults */
471
472 initialize_fbdev();
473 gltest();
474 shutdown_fbdev();
475
476 return 0;
477 }