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 14KB

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