422312c43211dd9c9279d63a414ccd0866759033
[winnie] / src / fbdev / gfx.cc
1 #ifdef WINNIE_FBDEV
2 #include <errno.h>
3 #include <limits.h>
4 #include <stdio.h>
5 #include <string.h>
6
7 #include <fcntl.h>
8 #include <sys/ioctl.h>
9 #include <sys/mman.h>
10 #include <sys/time.h>
11 #include <unistd.h>
12
13 #include <linux/fb.h>
14
15 #include "gfx.h"
16
17 #define FRAMEBUFFER_SIZE(xsz, ysz, bpp) ((xsz) * (ysz) * (bpp) / CHAR_BIT)
18
19 static unsigned char *framebuffer;
20 static int dev_fd = -1;
21
22 static Rect screen_rect;
23
24 static int color_depth; // bits per pixel
25
26 static Pixmap *pixmap;
27
28 bool init_gfx()
29 {
30         if((dev_fd = open("/dev/fb0", O_RDWR)) == -1) {
31                 fprintf(stderr, "Cannot open /dev/fb0 : %s\n", strerror(errno));
32                 return false;
33         }
34
35         fb_var_screeninfo sinfo;
36         if(ioctl(dev_fd, FBIOGET_VSCREENINFO, &sinfo) == -1) {
37                 close(dev_fd);
38                 dev_fd = -1;
39                 fprintf(stderr, "Unable to get screen info : %s\n", strerror(errno));
40                 return false;
41         }
42
43         printf("width : %d height : %d\n : bpp : %d\n", sinfo.xres, sinfo.yres, sinfo.bits_per_pixel);
44         printf("virtual w: %d virtual h: %d\n", sinfo.xres_virtual, sinfo.yres_virtual);
45
46         screen_rect.x = screen_rect.y = 0;
47         screen_rect.width = sinfo.xres_virtual;
48         screen_rect.height = sinfo.yres_virtual;
49         color_depth = sinfo.bits_per_pixel;
50
51         set_clipping_rect(screen_rect);
52
53         int sz = FRAMEBUFFER_SIZE(screen_rect.width, screen_rect.height, color_depth);
54         framebuffer = (unsigned char*)mmap(0, sz, PROT_READ | PROT_WRITE, MAP_SHARED, dev_fd, 0);
55
56         if(framebuffer == (void*)-1) {
57                 close(dev_fd);
58                 dev_fd = -1;
59                 fprintf(stderr, "Cannot map the framebuffer to memory : %s\n", strerror(errno));
60                 return false;
61         }
62
63 // TODO: uncomment when I find how to use intelfb instead of i915 GRRRR.-       
64         fb_vblank vblank;
65         if(ioctl(dev_fd, FBIOGET_VBLANK, &vblank) == -1) {
66 //              fprintf(stderr, "FBIOGET_VBLANK error: %s\n", strerror(errno));
67         }
68 /*      
69         else {
70                 printf("flags: %x\n", vblank.flags);
71                 printf("count: %d\n", vblank.count);
72                 printf("beam position: %d, %d\n", vblank.hcount, vblank.vcount);
73         }
74 */
75
76         pixmap = new Pixmap;
77         pixmap->width = screen_rect.width;
78         pixmap->height = screen_rect.height;
79         pixmap->pixels = framebuffer;
80
81         return true;
82 }
83
84 void destroy_gfx()
85 {
86         clear_screen(0, 0, 0);
87
88         if(dev_fd != -1) {
89                 close(dev_fd);
90         }
91
92         dev_fd = -1;
93
94         munmap(framebuffer, FRAMEBUFFER_SIZE(screen_rect.width, screen_rect.height, color_depth));
95         framebuffer = 0;
96
97         pixmap->pixels = 0;
98 }
99
100 unsigned char *get_framebuffer()
101 {
102         return framebuffer;
103 }
104
105 Pixmap *get_framebuffer_pixmap()
106 {
107         return pixmap;
108 }
109
110 Rect get_screen_size()
111 {
112         return screen_rect;
113 }
114
115 int get_color_depth()
116 {
117         return color_depth;
118 }
119
120
121 void set_cursor_visibility(bool visible)
122 {
123         fb_cursor curs;
124         curs.enable = visible ? 1 : 0;
125
126         if(ioctl(dev_fd, FBIO_CURSOR, &curs) == -1) {
127                 fprintf(stderr, "Cannot toggle cursor visibility : %s\n", strerror(errno));
128         }
129 }
130
131 void gfx_update()
132 {
133 }
134
135 void wait_vsync()
136 {
137         unsigned long arg = 0;
138         if(ioctl(dev_fd, FBIO_WAITFORVSYNC, &arg) == -1) {
139 //              printf("ioctl error %s\n", strerror(errno));
140         }
141 }
142
143 #endif // WINNIE_FBDEV