Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

glfbdevtest.c 15KB

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