c82ca6e5f6301fdc93b6840bb7b187ae611c1e32
[mesa.git] / progs / miniglx / glfbdevtest.c
1 /* $Id: glfbdevtest.c,v 1.1 2003/08/06 17:47:15 keithw Exp $ */
2
3 /*
4 * Test the GLFBDev interface. Only tested with radeonfb driver!!!!
5 */
6
7
8 #include <assert.h>
9 #include <errno.h>
10 #include <signal.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include <sys/ioctl.h>
17 #include <sys/mman.h>
18 #include <sys/types.h>
19 #include <linux/fb.h>
20 #include <linux/kd.h>
21 #include <linux/vt.h>
22 #include <GL/glut.h>
23 #include "GL/glfbdev.h"
24
25 #define DEFAULT_DEPTH 8
26
27 static struct fb_fix_screeninfo FixedInfo;
28 static struct fb_var_screeninfo VarInfo, OrigVarInfo;
29 static int DesiredDepth = 0;
30 static int OriginalVT = -1;
31 static int ConsoleFD = -1;
32 static int FrameBufferFD = -1;
33 static caddr_t FrameBuffer = (caddr_t) -1;
34 static caddr_t MMIOAddress = (caddr_t) -1;
35
36
37 static void
38 print_fixed_info(const struct fb_fix_screeninfo *fixed, const char *s)
39 {
40 static const char *visuals[] = {
41 "MONO01", "MONO10", "TRUECOLOR", "PSEUDOCOLOR",
42 "DIRECTCOLOR", "STATIC_PSEUDOCOLOR"
43 };
44
45 printf("%s info -----------------------\n", s);
46 printf("id = %16s\n", fixed->id);
47 printf("smem_start = 0x%x\n", fixed->smem_start);
48 printf("smem_len = %d (0x%x)\n", fixed->smem_len, fixed->smem_len);
49 printf("type = 0x%x\n", fixed->type);
50 printf("type_aux = 0x%x\n", fixed->type_aux);
51 printf("visual = 0x%x (%s)\n", fixed->visual, visuals[fixed->visual]);
52 printf("xpanstep = %d\n", fixed->xpanstep);
53 printf("ypanstep = %d\n", fixed->ypanstep);
54 printf("ywrapstep = %d\n", fixed->ywrapstep);
55 printf("line_length = %d\n", fixed->line_length);
56 printf("mmio_start = 0x%x\n", fixed->mmio_start);
57 printf("mmio_len = %d (0x%x)\n", fixed->mmio_len, fixed->mmio_len);
58 printf("accel = 0x%x\n", fixed->accel);
59 }
60
61
62 static void
63 print_var_info(const struct fb_var_screeninfo *var, const char *s)
64 {
65 printf("%s info -----------------------\n", s);
66 printf("xres = %d\n", var->xres);
67 printf("yres = %d\n", var->yres);
68 printf("xres_virtual = %d\n", var->xres_virtual);
69 printf("yres_virtual = %d\n", var->yres_virtual);
70 printf("xoffset = %d\n", var->xoffset);
71 printf("yoffset = %d\n", var->yoffset);
72 printf("bits_per_pixel = %d\n", var->bits_per_pixel);
73 printf("grayscale = %d\n", var->grayscale);
74
75 printf("red.offset = %d length = %d msb_right = %d\n",
76 var->red.offset, var->red.length, var->red.msb_right);
77 printf("green.offset = %d length = %d msb_right = %d\n",
78 var->green.offset, var->green.length, var->green.msb_right);
79 printf("blue.offset = %d length = %d msb_right = %d\n",
80 var->blue.offset, var->blue.length, var->blue.msb_right);
81 printf("transp.offset = %d length = %d msb_right = %d\n",
82 var->transp.offset, var->transp.length, var->transp.msb_right);
83
84 printf("nonstd = %d\n", var->nonstd);
85 printf("activate = %d\n", var->activate);
86 printf("height = %d mm\n", var->height);
87 printf("width = %d mm\n", var->width);
88 printf("accel_flags = 0x%x\n", var->accel_flags);
89 printf("pixclock = %d\n", var->pixclock);
90 printf("left_margin = %d\n", var->left_margin);
91 printf("right_margin = %d\n", var->right_margin);
92 printf("upper_margin = %d\n", var->upper_margin);
93 printf("lower_margin = %d\n", var->lower_margin);
94 printf("hsync_len = %d\n", var->hsync_len);
95 printf("vsync_len = %d\n", var->vsync_len);
96 printf("sync = %d\n", var->sync);
97 printf("vmode = %d\n", var->vmode);
98 }
99
100
101 static void
102 signal_handler(int signumber)
103 {
104 signal(signumber, SIG_IGN); /* prevent recursion! */
105 fprintf(stderr, "error: got signal %d (exiting)\n", signumber);
106 exit(1);
107 }
108
109
110 static void
111 initialize_fbdev( void )
112 {
113 char ttystr[1000];
114 int fd, vtnumber, ttyfd;
115 int sz;
116
117 if (geteuid()) {
118 fprintf(stderr, "error: you need to be root\n");
119 exit(1);
120 }
121
122 #if 1
123 /* open the framebuffer device */
124 FrameBufferFD = open("/dev/fb0", O_RDWR);
125 if (FrameBufferFD < 0) {
126 fprintf(stderr, "Error opening /dev/fb0: %s\n", strerror(errno));
127 exit(1);
128 }
129 #endif
130
131 /* open /dev/tty0 and get the vt number */
132 if ((fd = open("/dev/tty0", O_WRONLY, 0)) < 0) {
133 fprintf(stderr, "error opening /dev/tty0\n");
134 exit(1);
135 }
136 if (ioctl(fd, VT_OPENQRY, &vtnumber) < 0 || vtnumber < 0) {
137 fprintf(stderr, "error: couldn't get a free vt\n");
138 exit(1);
139 }
140 close(fd);
141
142 /* open the console tty */
143 sprintf(ttystr, "/dev/tty%d", vtnumber); /* /dev/tty1-64 */
144 ConsoleFD = open(ttystr, O_RDWR | O_NDELAY, 0);
145 if (ConsoleFD < 0) {
146 fprintf(stderr, "error couldn't open console fd\n");
147 exit(1);
148 }
149
150 /* save current vt number */
151 {
152 struct vt_stat vts;
153 if (ioctl(ConsoleFD, VT_GETSTATE, &vts) == 0)
154 OriginalVT = vts.v_active;
155 }
156
157 /* disconnect from controlling tty */
158 ttyfd = open("/dev/tty", O_RDWR);
159 if (ttyfd >= 0) {
160 ioctl(ttyfd, TIOCNOTTY, 0);
161 close(ttyfd);
162 }
163
164 /* some magic to restore the vt when we exit */
165 {
166 struct vt_mode vt;
167 if (ioctl(ConsoleFD, VT_ACTIVATE, vtnumber) != 0)
168 printf("ioctl VT_ACTIVATE: %s\n", strerror(errno));
169 if (ioctl(ConsoleFD, VT_WAITACTIVE, vtnumber) != 0)
170 printf("ioctl VT_WAITACTIVE: %s\n", strerror(errno));
171
172 if (ioctl(ConsoleFD, VT_GETMODE, &vt) < 0) {
173 fprintf(stderr, "error: ioctl VT_GETMODE: %s\n", strerror(errno));
174 exit(1);
175 }
176
177 vt.mode = VT_PROCESS;
178 vt.relsig = SIGUSR1;
179 vt.acqsig = SIGUSR1;
180 if (ioctl(ConsoleFD, VT_SETMODE, &vt) < 0) {
181 fprintf(stderr, "error: ioctl(VT_SETMODE) failed: %s\n",
182 strerror(errno));
183 exit(1);
184 }
185 }
186
187 /* go into graphics mode */
188 if (ioctl(ConsoleFD, KDSETMODE, KD_GRAPHICS) < 0) {
189 fprintf(stderr, "error: ioctl(KDSETMODE, KD_GRAPHICS) failed: %s\n",
190 strerror(errno));
191 exit(1);
192 }
193
194
195 #if 0
196 /* open the framebuffer device */
197 FrameBufferFD = open("/dev/fb0", O_RDWR);
198 if (FrameBufferFD < 0) {
199 fprintf(stderr, "Error opening /dev/fb0: %s\n", strerror(errno));
200 exit(1);
201 }
202 #endif
203
204 /* Get the fixed screen info */
205 if (ioctl(FrameBufferFD, FBIOGET_FSCREENINFO, &FixedInfo)) {
206 fprintf(stderr, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
207 strerror(errno));
208 exit(1);
209 }
210
211 print_fixed_info(&FixedInfo, "Fixed");
212
213
214 /* get the variable screen info */
215 if (ioctl(FrameBufferFD, FBIOGET_VSCREENINFO, &OrigVarInfo)) {
216 fprintf(stderr, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
217 strerror(errno));
218 exit(1);
219 }
220
221 print_var_info(&OrigVarInfo, "Orig Var");
222
223 /* operate on a copy */
224 VarInfo = OrigVarInfo;
225
226 /* set the depth, resolution, etc */
227 DesiredDepth = 32;
228 if (DesiredDepth)
229 VarInfo.bits_per_pixel = DesiredDepth;
230
231 if (VarInfo.bits_per_pixel == 16) {
232 VarInfo.red.offset = 11;
233 VarInfo.green.offset = 5;
234 VarInfo.blue.offset = 0;
235 VarInfo.red.length = 5;
236 VarInfo.green.length = 6;
237 VarInfo.blue.length = 5;
238 VarInfo.transp.offset = 0;
239 VarInfo.transp.length = 0;
240 }
241 else if (VarInfo.bits_per_pixel == 32) {
242 VarInfo.red.offset = 16;
243 VarInfo.green.offset = 8;
244 VarInfo.blue.offset = 0;
245 VarInfo.transp.offset = 24;
246 VarInfo.red.length = 8;
247 VarInfo.green.length = 8;
248 VarInfo.blue.length = 8;
249 VarInfo.transp.length = 8;
250 }
251 /* timing values taken from /etc/fb.modes (1280x1024 @ 75Hz) */
252 VarInfo.xres_virtual = VarInfo.xres = 1280;
253 VarInfo.yres_virtual = VarInfo.yres = 1024;
254 VarInfo.pixclock = 7408;
255 VarInfo.left_margin = 248;
256 VarInfo.right_margin = 16;
257 VarInfo.upper_margin = 38;
258 VarInfo.lower_margin = 1;
259 VarInfo.hsync_len = 144;
260 VarInfo.vsync_len = 3;
261
262 VarInfo.xoffset = 0;
263 VarInfo.yoffset = 0;
264 VarInfo.nonstd = 0;
265 VarInfo.vmode &= ~FB_VMODE_YWRAP; /* turn off scrolling */
266
267 /* set new variable screen info */
268 if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &VarInfo)) {
269 fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
270 strerror(errno));
271 exit(1);
272 }
273
274 print_var_info(&VarInfo, "New Var");
275
276 if (FixedInfo.visual != FB_VISUAL_TRUECOLOR &&
277 FixedInfo.visual != FB_VISUAL_DIRECTCOLOR) {
278 fprintf(stderr, "non-TRUE/DIRECT-COLOR visuals (0x%x) not supported by this demo.\n", FixedInfo.visual);
279 exit(1);
280 }
281
282 /* initialize colormap */
283 if (FixedInfo.visual == FB_VISUAL_DIRECTCOLOR) {
284 struct fb_cmap cmap;
285 unsigned short red[256], green[256], blue[256];
286 int i;
287
288 /* we're assuming 256 entries here */
289 printf("initializing directcolor colormap\n");
290 cmap.start = 0;
291 cmap.len = 256;
292 cmap.red = red;
293 cmap.green = green;
294 cmap.blue = blue;
295 cmap.transp = NULL;
296 for (i = 0; i < cmap.len; i++) {
297 red[i] = green[i] = blue[i] = (i << 8) | i;
298 }
299 if (ioctl(FrameBufferFD, FBIOPUTCMAP, (void *) &cmap) < 0) {
300 fprintf(stderr, "ioctl(FBIOPUTCMAP) failed [%d]\n", i);
301 }
302 }
303
304 /*
305 * fbdev says the frame buffer is at offset zero, and the mmio region
306 * is immediately after.
307 */
308
309 /* mmap the framebuffer into our address space */
310 FrameBuffer = (caddr_t) mmap(0, /* start */
311 FixedInfo.smem_len, /* bytes */
312 PROT_READ | PROT_WRITE, /* prot */
313 MAP_SHARED, /* flags */
314 FrameBufferFD, /* fd */
315 0 /* offset */);
316 if (FrameBuffer == (caddr_t) - 1) {
317 fprintf(stderr, "error: unable to mmap framebuffer: %s\n",
318 strerror(errno));
319 exit(1);
320 }
321 printf("FrameBuffer = %p\n", FrameBuffer);
322
323 #if 1
324 /* mmap the MMIO region into our address space */
325 MMIOAddress = (caddr_t) mmap(0, /* start */
326 FixedInfo.mmio_len, /* bytes */
327 PROT_READ | PROT_WRITE, /* prot */
328 MAP_SHARED, /* flags */
329 FrameBufferFD, /* fd */
330 FixedInfo.smem_len /* offset */);
331 if (MMIOAddress == (caddr_t) - 1) {
332 fprintf(stderr, "error: unable to mmap mmio region: %s\n",
333 strerror(errno));
334 }
335 printf("MMIOAddress = %p\n", MMIOAddress);
336
337 /* try out some simple MMIO register reads */
338 if (1)
339 {
340 typedef unsigned int CARD32;
341 typedef unsigned char CARD8;
342 #define RADEON_CONFIG_MEMSIZE 0x00f8
343 #define RADEON_MEM_SDRAM_MODE_REG 0x0158
344 #define MMIO_IN32(base, offset) \
345 *(volatile CARD32 *)(void *)(((CARD8*)(base)) + (offset))
346 #define INREG(addr) MMIO_IN32(MMIOAddress, addr)
347 int sz, type;
348 const char *typeStr[] = {"SDR", "DDR", "64-bit SDR"};
349 sz = INREG(RADEON_CONFIG_MEMSIZE);
350 type = INREG(RADEON_MEM_SDRAM_MODE_REG);
351 printf("RADEON_CONFIG_MEMSIZE = %d (%d MB)\n", sz, sz / 1024 / 1024);
352 printf("RADEON_MEM_SDRAM_MODE_REG >> 30 = %d (%s)\n",
353 type >> 30, typeStr[type>>30]);
354 }
355 #endif
356
357 }
358
359
360 static void
361 shutdown_fbdev( void )
362 {
363 struct vt_mode VT;
364
365 printf("cleaning up...\n");
366 /* restore original variable screen info */
367 if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &OrigVarInfo)) {
368 fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
369 strerror(errno));
370 exit(1);
371 }
372
373 munmap(MMIOAddress, FixedInfo.mmio_len);
374 munmap(FrameBuffer, FixedInfo.smem_len);
375 close(FrameBufferFD);
376
377 /* restore text mode */
378 ioctl(ConsoleFD, KDSETMODE, KD_TEXT);
379
380 /* set vt */
381 if (ioctl(ConsoleFD, VT_GETMODE, &VT) != -1) {
382 VT.mode = VT_AUTO;
383 ioctl(ConsoleFD, VT_SETMODE, &VT);
384 }
385
386 /* restore original vt */
387 if (OriginalVT >= 0) {
388 ioctl(ConsoleFD, VT_ACTIVATE, OriginalVT);
389 OriginalVT = -1;
390 }
391
392 close(ConsoleFD);
393 }
394
395
396 static void
397 gltest( void )
398 {
399 static const int attribs[] = {
400 GLFBDEV_DOUBLE_BUFFER,
401 GLFBDEV_DEPTH_SIZE, 16,
402 GLFBDEV_NONE
403 };
404 GLFBDevContextPtr ctx;
405 GLFBDevBufferPtr buf;
406 GLFBDevVisualPtr vis;
407 int bytes, r, g, b, a;
408 float ang;
409
410 printf("GLFBDEV_VENDOR = %s\n", glFBDevGetString(GLFBDEV_VENDOR));
411 printf("GLFBDEV_VERSION = %s\n", glFBDevGetString(GLFBDEV_VERSION));
412
413 /* framebuffer size */
414 bytes = VarInfo.xres_virtual * VarInfo.yres_virtual * VarInfo.bits_per_pixel / 8;
415
416 vis = glFBDevCreateVisual( &FixedInfo, &VarInfo, attribs );
417 assert(vis);
418
419 buf = glFBDevCreateBuffer( &FixedInfo, &VarInfo, vis, FrameBuffer, NULL, bytes );
420 assert(buf);
421
422 ctx = glFBDevCreateContext( vis, NULL );
423 assert(buf);
424
425 b = glFBDevMakeCurrent( ctx, buf, buf );
426 assert(b);
427
428 /*printf("GL_EXTENSIONS: %s\n", glGetString(GL_EXTENSIONS));*/
429 glGetIntegerv(GL_RED_BITS, &r);
430 glGetIntegerv(GL_GREEN_BITS, &g);
431 glGetIntegerv(GL_BLUE_BITS, &b);
432 glGetIntegerv(GL_ALPHA_BITS, &a);
433 printf("RED_BITS=%d GREEN_BITS=%d BLUE_BITS=%d ALPHA_BITS=%d\n",
434 r, g, b, a);
435
436 glClearColor(0.5, 0.5, 1.0, 0);
437 glMatrixMode(GL_PROJECTION);
438 glLoadIdentity();
439 glFrustum(-1, 1, -1, 1, 2, 30);
440 glMatrixMode(GL_MODELVIEW);
441 glLoadIdentity();
442 glTranslatef(0, 0, -15);
443 glViewport(0, 0, VarInfo.xres_virtual, VarInfo.yres_virtual);
444 glEnable(GL_LIGHTING);
445 glEnable(GL_LIGHT0);
446 glEnable(GL_DEPTH_TEST);
447
448 for (ang = 0; ang <= 180; ang += 15) {
449 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
450 glPushMatrix();
451 glRotatef(ang, 1, 0, 0);
452 glutSolidTorus(1, 3, 40, 20);
453 glPopMatrix();
454 glFBDevSwapBuffers(buf);
455 }
456
457 /* clean up */
458 b = glFBDevMakeCurrent( NULL, NULL, NULL);
459 assert(b);
460
461 glFBDevDestroyContext(ctx);
462 glFBDevDestroyBuffer(buf);
463 glFBDevDestroyVisual(vis);
464 }
465
466
467 int
468 main( int argc, char *argv[] )
469 {
470 signal(SIGUSR1, signal_handler); /* exit if someone tries a vt switch */
471 signal(SIGSEGV, signal_handler); /* catch segfaults */
472
473 initialize_fbdev();
474 gltest();
475 shutdown_fbdev();
476
477 return 0;
478 }