xref: /aosp_15_r20/system/extras/tests/framebuffer/fb_test.c (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
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