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