1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker * Copyright (C) 2007 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker *
4*288bf522SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker *
8*288bf522SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker *
10*288bf522SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker */
16*288bf522SAndroid Build Coastguard Worker
17*288bf522SAndroid Build Coastguard Worker #include <stdlib.h>
18*288bf522SAndroid Build Coastguard Worker #include <unistd.h>
19*288bf522SAndroid Build Coastguard Worker
20*288bf522SAndroid Build Coastguard Worker #include <fcntl.h>
21*288bf522SAndroid Build Coastguard Worker #include <stdio.h>
22*288bf522SAndroid Build Coastguard Worker
23*288bf522SAndroid Build Coastguard Worker #include <sys/ioctl.h>
24*288bf522SAndroid Build Coastguard Worker #include <sys/mman.h>
25*288bf522SAndroid Build Coastguard Worker #include <sys/types.h>
26*288bf522SAndroid Build Coastguard Worker #include <time.h>
27*288bf522SAndroid Build Coastguard Worker
28*288bf522SAndroid Build Coastguard Worker #include <linux/fb.h>
29*288bf522SAndroid Build Coastguard Worker #include <linux/kd.h>
30*288bf522SAndroid Build Coastguard Worker
31*288bf522SAndroid Build Coastguard Worker struct simple_fb {
32*288bf522SAndroid Build Coastguard Worker void *data;
33*288bf522SAndroid Build Coastguard Worker int width;
34*288bf522SAndroid Build Coastguard Worker int height;
35*288bf522SAndroid Build Coastguard Worker int stride;
36*288bf522SAndroid Build Coastguard Worker int bpp;
37*288bf522SAndroid Build Coastguard Worker };
38*288bf522SAndroid Build Coastguard Worker
39*288bf522SAndroid Build Coastguard Worker static struct simple_fb gr_fbs[2];
40*288bf522SAndroid Build Coastguard Worker static unsigned gr_active_fb = 0;
41*288bf522SAndroid Build Coastguard Worker
42*288bf522SAndroid Build Coastguard Worker static int gr_fb_fd = -1;
43*288bf522SAndroid Build Coastguard Worker static int gr_vt_fd = -1;
44*288bf522SAndroid Build Coastguard Worker
45*288bf522SAndroid Build Coastguard Worker static struct fb_var_screeninfo vi;
46*288bf522SAndroid Build Coastguard Worker struct fb_fix_screeninfo fi;
47*288bf522SAndroid Build Coastguard Worker struct timespec tv, tv2;
48*288bf522SAndroid Build Coastguard Worker
49*288bf522SAndroid Build Coastguard Worker static void dumpinfo(struct fb_fix_screeninfo *fi,
50*288bf522SAndroid Build Coastguard Worker struct fb_var_screeninfo *vi);
51*288bf522SAndroid Build Coastguard Worker
get_framebuffer(struct simple_fb * fb,unsigned bpp)52*288bf522SAndroid Build Coastguard Worker static int get_framebuffer(struct simple_fb *fb, unsigned bpp)
53*288bf522SAndroid Build Coastguard Worker {
54*288bf522SAndroid Build Coastguard Worker int fd;
55*288bf522SAndroid Build Coastguard Worker void *bits;
56*288bf522SAndroid Build Coastguard Worker int bytes_per_pixel;
57*288bf522SAndroid Build Coastguard Worker
58*288bf522SAndroid Build Coastguard Worker fd = open("/dev/graphics/fb0", O_RDWR);
59*288bf522SAndroid Build Coastguard Worker if (fd < 0) {
60*288bf522SAndroid Build Coastguard Worker printf("cannot open /dev/graphics/fb0, retrying with /dev/fb0\n");
61*288bf522SAndroid Build Coastguard Worker if ((fd = open("/dev/fb0", O_RDWR)) < 0) {
62*288bf522SAndroid Build Coastguard Worker perror("cannot open /dev/fb0");
63*288bf522SAndroid Build Coastguard Worker return -1;
64*288bf522SAndroid Build Coastguard Worker }
65*288bf522SAndroid Build Coastguard Worker }
66*288bf522SAndroid Build Coastguard Worker
67*288bf522SAndroid Build Coastguard Worker if(ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) {
68*288bf522SAndroid Build Coastguard Worker perror("failed to get fb0 info");
69*288bf522SAndroid Build Coastguard Worker return -1;
70*288bf522SAndroid Build Coastguard Worker }
71*288bf522SAndroid Build Coastguard Worker
72*288bf522SAndroid Build Coastguard Worker if (bpp && vi.bits_per_pixel != bpp) {
73*288bf522SAndroid Build Coastguard Worker printf("bpp != %d, forcing...\n", bpp);
74*288bf522SAndroid Build Coastguard Worker vi.bits_per_pixel = bpp;
75*288bf522SAndroid Build Coastguard Worker if(ioctl(fd, FBIOPUT_VSCREENINFO, &vi) < 0) {
76*288bf522SAndroid Build Coastguard Worker perror("failed to force bpp");
77*288bf522SAndroid Build Coastguard Worker return -1;
78*288bf522SAndroid Build Coastguard Worker }
79*288bf522SAndroid Build Coastguard Worker }
80*288bf522SAndroid Build Coastguard Worker
81*288bf522SAndroid Build Coastguard Worker if(ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) {
82*288bf522SAndroid Build Coastguard Worker perror("failed to get fb0 info");
83*288bf522SAndroid Build Coastguard Worker return -1;
84*288bf522SAndroid Build Coastguard Worker }
85*288bf522SAndroid Build Coastguard Worker
86*288bf522SAndroid Build Coastguard Worker dumpinfo(&fi, &vi);
87*288bf522SAndroid Build Coastguard Worker
88*288bf522SAndroid Build Coastguard Worker bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
89*288bf522SAndroid Build Coastguard Worker if(bits == MAP_FAILED) {
90*288bf522SAndroid Build Coastguard Worker perror("failed to mmap framebuffer");
91*288bf522SAndroid Build Coastguard Worker return -1;
92*288bf522SAndroid Build Coastguard Worker }
93*288bf522SAndroid Build Coastguard Worker
94*288bf522SAndroid Build Coastguard Worker bytes_per_pixel = vi.bits_per_pixel >> 3;
95*288bf522SAndroid Build Coastguard Worker
96*288bf522SAndroid Build Coastguard Worker fb->width = vi.xres;
97*288bf522SAndroid Build Coastguard Worker fb->height = vi.yres;
98*288bf522SAndroid Build Coastguard Worker fb->stride = fi.line_length / bytes_per_pixel;
99*288bf522SAndroid Build Coastguard Worker fb->data = bits;
100*288bf522SAndroid Build Coastguard Worker fb->bpp = vi.bits_per_pixel;
101*288bf522SAndroid Build Coastguard Worker
102*288bf522SAndroid Build Coastguard Worker fb++;
103*288bf522SAndroid Build Coastguard Worker
104*288bf522SAndroid Build Coastguard Worker fb->width = vi.xres;
105*288bf522SAndroid Build Coastguard Worker fb->height = vi.yres;
106*288bf522SAndroid Build Coastguard Worker fb->stride = fi.line_length / bytes_per_pixel;
107*288bf522SAndroid Build Coastguard Worker fb->data = (void *)((unsigned long)bits +
108*288bf522SAndroid Build Coastguard Worker vi.yres * vi.xres * bytes_per_pixel);
109*288bf522SAndroid Build Coastguard Worker fb->bpp = vi.bits_per_pixel;
110*288bf522SAndroid Build Coastguard Worker
111*288bf522SAndroid Build Coastguard Worker return fd;
112*288bf522SAndroid Build Coastguard Worker }
113*288bf522SAndroid Build Coastguard Worker
set_active_framebuffer(unsigned n)114*288bf522SAndroid Build Coastguard Worker static void set_active_framebuffer(unsigned n)
115*288bf522SAndroid Build Coastguard Worker {
116*288bf522SAndroid Build Coastguard Worker if(n > 1) return;
117*288bf522SAndroid Build Coastguard Worker vi.yres_virtual = vi.yres * 2;
118*288bf522SAndroid Build Coastguard Worker vi.yoffset = n * vi.yres;
119*288bf522SAndroid Build Coastguard Worker if(ioctl(gr_fb_fd, FBIOPUT_VSCREENINFO, &vi) < 0) {
120*288bf522SAndroid Build Coastguard Worker fprintf(stderr,"active fb swap failed!\n");
121*288bf522SAndroid Build Coastguard Worker } else
122*288bf522SAndroid Build Coastguard Worker printf("active buffer: %d\n", n);
123*288bf522SAndroid Build Coastguard Worker }
124*288bf522SAndroid Build Coastguard Worker
dumpinfo(struct fb_fix_screeninfo * fi,struct fb_var_screeninfo * vi)125*288bf522SAndroid Build Coastguard Worker static void dumpinfo(struct fb_fix_screeninfo *fi, struct fb_var_screeninfo *vi)
126*288bf522SAndroid Build Coastguard Worker {
127*288bf522SAndroid Build Coastguard Worker fprintf(stderr,"vi.xres = %d\n", vi->xres);
128*288bf522SAndroid Build Coastguard Worker fprintf(stderr,"vi.yres = %d\n", vi->yres);
129*288bf522SAndroid Build Coastguard Worker fprintf(stderr,"vi.xresv = %d\n", vi->xres_virtual);
130*288bf522SAndroid Build Coastguard Worker fprintf(stderr,"vi.yresv = %d\n", vi->yres_virtual);
131*288bf522SAndroid Build Coastguard Worker fprintf(stderr,"vi.xoff = %d\n", vi->xoffset);
132*288bf522SAndroid Build Coastguard Worker fprintf(stderr,"vi.yoff = %d\n", vi->yoffset);
133*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "vi.bits_per_pixel = %d\n", vi->bits_per_pixel);
134*288bf522SAndroid Build Coastguard Worker
135*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "fi.line_length = %d\n", fi->line_length);
136*288bf522SAndroid Build Coastguard Worker
137*288bf522SAndroid Build Coastguard Worker }
138*288bf522SAndroid Build Coastguard Worker
gr_init(int bpp,int id)139*288bf522SAndroid Build Coastguard Worker int gr_init(int bpp, int id)
140*288bf522SAndroid Build Coastguard Worker {
141*288bf522SAndroid Build Coastguard Worker int fd = -1;
142*288bf522SAndroid Build Coastguard Worker
143*288bf522SAndroid Build Coastguard Worker if (!access("/dev/tty0", F_OK)) {
144*288bf522SAndroid Build Coastguard Worker fd = open("/dev/tty0", O_RDWR | O_SYNC);
145*288bf522SAndroid Build Coastguard Worker if(fd < 0)
146*288bf522SAndroid Build Coastguard Worker return -1;
147*288bf522SAndroid Build Coastguard Worker
148*288bf522SAndroid Build Coastguard Worker if(ioctl(fd, KDSETMODE, (void*) KD_GRAPHICS)) {
149*288bf522SAndroid Build Coastguard Worker close(fd);
150*288bf522SAndroid Build Coastguard Worker return -1;
151*288bf522SAndroid Build Coastguard Worker }
152*288bf522SAndroid Build Coastguard Worker }
153*288bf522SAndroid Build Coastguard Worker
154*288bf522SAndroid Build Coastguard Worker gr_fb_fd = get_framebuffer(gr_fbs, bpp);
155*288bf522SAndroid Build Coastguard Worker
156*288bf522SAndroid Build Coastguard Worker if(gr_fb_fd < 0) {
157*288bf522SAndroid Build Coastguard Worker if (fd >= 0) {
158*288bf522SAndroid Build Coastguard Worker ioctl(fd, KDSETMODE, (void*) KD_TEXT);
159*288bf522SAndroid Build Coastguard Worker close(fd);
160*288bf522SAndroid Build Coastguard Worker }
161*288bf522SAndroid Build Coastguard Worker return -1;
162*288bf522SAndroid Build Coastguard Worker }
163*288bf522SAndroid Build Coastguard Worker
164*288bf522SAndroid Build Coastguard Worker gr_vt_fd = fd;
165*288bf522SAndroid Build Coastguard Worker
166*288bf522SAndroid Build Coastguard Worker /* start with 0 as front (displayed) and 1 as back (drawing) */
167*288bf522SAndroid Build Coastguard Worker gr_active_fb = id;
168*288bf522SAndroid Build Coastguard Worker set_active_framebuffer(id);
169*288bf522SAndroid Build Coastguard Worker
170*288bf522SAndroid Build Coastguard Worker return 0;
171*288bf522SAndroid Build Coastguard Worker }
172*288bf522SAndroid Build Coastguard Worker
gr_exit(void)173*288bf522SAndroid Build Coastguard Worker void gr_exit(void)
174*288bf522SAndroid Build Coastguard Worker {
175*288bf522SAndroid Build Coastguard Worker close(gr_fb_fd);
176*288bf522SAndroid Build Coastguard Worker gr_fb_fd = -1;
177*288bf522SAndroid Build Coastguard Worker
178*288bf522SAndroid Build Coastguard Worker if (gr_vt_fd >= 0) {
179*288bf522SAndroid Build Coastguard Worker ioctl(gr_vt_fd, KDSETMODE, (void*) KD_TEXT);
180*288bf522SAndroid Build Coastguard Worker close(gr_vt_fd);
181*288bf522SAndroid Build Coastguard Worker gr_vt_fd = -1;
182*288bf522SAndroid Build Coastguard Worker }
183*288bf522SAndroid Build Coastguard Worker }
184*288bf522SAndroid Build Coastguard Worker
gr_fb_width(void)185*288bf522SAndroid Build Coastguard Worker int gr_fb_width(void)
186*288bf522SAndroid Build Coastguard Worker {
187*288bf522SAndroid Build Coastguard Worker return gr_fbs[0].width;
188*288bf522SAndroid Build Coastguard Worker }
189*288bf522SAndroid Build Coastguard Worker
gr_fb_height(void)190*288bf522SAndroid Build Coastguard Worker int gr_fb_height(void)
191*288bf522SAndroid Build Coastguard Worker {
192*288bf522SAndroid Build Coastguard Worker return gr_fbs[0].height;
193*288bf522SAndroid Build Coastguard Worker }
194*288bf522SAndroid Build Coastguard Worker
195*288bf522SAndroid Build Coastguard Worker uint16_t red = 0xf800;
196*288bf522SAndroid Build Coastguard Worker uint16_t green = 0x07e0;
197*288bf522SAndroid Build Coastguard Worker uint16_t blue = 0x001f;
198*288bf522SAndroid Build Coastguard Worker uint16_t white = 0xffff;
199*288bf522SAndroid Build Coastguard Worker uint16_t black = 0x0;
200*288bf522SAndroid Build Coastguard Worker
201*288bf522SAndroid Build Coastguard Worker uint32_t red32 = 0x00ff0000;
202*288bf522SAndroid Build Coastguard Worker uint32_t green32 = 0x0000ff00;
203*288bf522SAndroid Build Coastguard Worker uint32_t blue32 = 0x000000ff;
204*288bf522SAndroid Build Coastguard Worker uint32_t white32 = 0x00ffffff;
205*288bf522SAndroid Build Coastguard Worker uint32_t black32 = 0x0;
206*288bf522SAndroid Build Coastguard Worker
draw_grid(int w,int h,void * _loc)207*288bf522SAndroid Build Coastguard Worker void draw_grid(int w, int h, void* _loc) {
208*288bf522SAndroid Build Coastguard Worker int i, j;
209*288bf522SAndroid Build Coastguard Worker int stride = fi.line_length / (vi.bits_per_pixel >> 3);
210*288bf522SAndroid Build Coastguard Worker uint16_t *loc = _loc;
211*288bf522SAndroid Build Coastguard Worker uint32_t *loc32 = _loc;
212*288bf522SAndroid Build Coastguard Worker
213*288bf522SAndroid Build Coastguard Worker for (j = 0; j < h/2; j++) {
214*288bf522SAndroid Build Coastguard Worker for (i = 0; i < w/2; i++)
215*288bf522SAndroid Build Coastguard Worker if (vi.bits_per_pixel == 16)
216*288bf522SAndroid Build Coastguard Worker loc[i + j*(stride)] = red;
217*288bf522SAndroid Build Coastguard Worker else
218*288bf522SAndroid Build Coastguard Worker loc32[i + j*(stride)] = red32;
219*288bf522SAndroid Build Coastguard Worker for (; i < w; i++)
220*288bf522SAndroid Build Coastguard Worker if (vi.bits_per_pixel == 16)
221*288bf522SAndroid Build Coastguard Worker loc[i + j*(stride)] = green;
222*288bf522SAndroid Build Coastguard Worker else
223*288bf522SAndroid Build Coastguard Worker loc32[i + j*(stride)] = green32;
224*288bf522SAndroid Build Coastguard Worker }
225*288bf522SAndroid Build Coastguard Worker
226*288bf522SAndroid Build Coastguard Worker for (; j < h; j++) {
227*288bf522SAndroid Build Coastguard Worker for (i = 0; i < w/2; i++)
228*288bf522SAndroid Build Coastguard Worker if (vi.bits_per_pixel == 16)
229*288bf522SAndroid Build Coastguard Worker loc[i + j*(stride)] = blue;
230*288bf522SAndroid Build Coastguard Worker else
231*288bf522SAndroid Build Coastguard Worker loc32[i + j*(stride)] = blue32;
232*288bf522SAndroid Build Coastguard Worker for (; i < w; i++)
233*288bf522SAndroid Build Coastguard Worker if (vi.bits_per_pixel == 16)
234*288bf522SAndroid Build Coastguard Worker loc[i + j*(stride)] = white;
235*288bf522SAndroid Build Coastguard Worker else
236*288bf522SAndroid Build Coastguard Worker loc32[i + j*(stride)] = white32;
237*288bf522SAndroid Build Coastguard Worker }
238*288bf522SAndroid Build Coastguard Worker
239*288bf522SAndroid Build Coastguard Worker }
240*288bf522SAndroid Build Coastguard Worker
clear_screen(int w,int h,void * _loc)241*288bf522SAndroid Build Coastguard Worker void clear_screen(int w, int h, void* _loc)
242*288bf522SAndroid Build Coastguard Worker {
243*288bf522SAndroid Build Coastguard Worker int i,j;
244*288bf522SAndroid Build Coastguard Worker int stride = fi.line_length / (vi.bits_per_pixel >> 3);
245*288bf522SAndroid Build Coastguard Worker uint16_t *loc = _loc;
246*288bf522SAndroid Build Coastguard Worker uint32_t *loc32 = _loc;
247*288bf522SAndroid Build Coastguard Worker
248*288bf522SAndroid Build Coastguard Worker for (j = 0; j < h; j++)
249*288bf522SAndroid Build Coastguard Worker for (i = 0; i < w; i++)
250*288bf522SAndroid Build Coastguard Worker if (vi.bits_per_pixel == 16)
251*288bf522SAndroid Build Coastguard Worker loc[i + j*(stride)] = black;
252*288bf522SAndroid Build Coastguard Worker else
253*288bf522SAndroid Build Coastguard Worker loc32[i + j*(stride)] = black32;
254*288bf522SAndroid Build Coastguard Worker }
255*288bf522SAndroid Build Coastguard Worker
main(int argc,char ** argv)256*288bf522SAndroid Build Coastguard Worker int main(int argc, char **argv) {
257*288bf522SAndroid Build Coastguard Worker int w;
258*288bf522SAndroid Build Coastguard Worker int h;
259*288bf522SAndroid Build Coastguard Worker int id = 0;
260*288bf522SAndroid Build Coastguard Worker int bpp = 0;
261*288bf522SAndroid Build Coastguard Worker
262*288bf522SAndroid Build Coastguard Worker if (argc > 1)
263*288bf522SAndroid Build Coastguard Worker bpp = atoi(argv[1]);
264*288bf522SAndroid Build Coastguard Worker
265*288bf522SAndroid Build Coastguard Worker if (argc > 4)
266*288bf522SAndroid Build Coastguard Worker id = !!atoi(argv[4]);
267*288bf522SAndroid Build Coastguard Worker
268*288bf522SAndroid Build Coastguard Worker gr_init(bpp, id);
269*288bf522SAndroid Build Coastguard Worker
270*288bf522SAndroid Build Coastguard Worker if (argc > 3) {
271*288bf522SAndroid Build Coastguard Worker w = atoi(argv[2]);
272*288bf522SAndroid Build Coastguard Worker h = atoi(argv[3]);
273*288bf522SAndroid Build Coastguard Worker } else {
274*288bf522SAndroid Build Coastguard Worker w = vi.xres;
275*288bf522SAndroid Build Coastguard Worker h = vi.yres;
276*288bf522SAndroid Build Coastguard Worker }
277*288bf522SAndroid Build Coastguard Worker
278*288bf522SAndroid Build Coastguard Worker clear_screen(vi.xres, vi.yres, gr_fbs[0].data);
279*288bf522SAndroid Build Coastguard Worker clear_screen(vi.xres, vi.yres, gr_fbs[1].data);
280*288bf522SAndroid Build Coastguard Worker
281*288bf522SAndroid Build Coastguard Worker draw_grid(w, h, gr_fbs[id].data);
282*288bf522SAndroid Build Coastguard Worker
283*288bf522SAndroid Build Coastguard Worker set_active_framebuffer(!id);
284*288bf522SAndroid Build Coastguard Worker set_active_framebuffer(id);
285*288bf522SAndroid Build Coastguard Worker
286*288bf522SAndroid Build Coastguard Worker return 0;
287*288bf522SAndroid Build Coastguard Worker }
288