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