1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 * Copyright (c) 2014 The Android Open Source Project
5 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
31 #include <sys/cdefs.h>
32 #include <sys/ioctl.h>
33 #include <sys/types.h>
39 static gr_surface fbdev_init(gr_backend *);
40 static gr_surface fbdev_flip(gr_backend *);
41 static bool fbdev_exit(gr_backend *);
43 fbdev_common fb_data = {
45 .displayed_buffer = 0,
49 static gr_backend my_backend = {
53 .data = (void *)&fb_data
56 gr_backend *open_fbdev(void) {
60 static void fbdev_blank(gr_backend *backend, bool blank) {
62 fbdev_common *fb = (fbdev_common *)backend->data;
64 ret = ioctl(fb->fd, FBIOBLANK, blank ? FB_BLANK_POWERDOWN :
67 perror("ioctl(): blank");
70 static void set_displayed_framebuffer(fbdev_common *fb, unsigned int n) {
77 fb->vi.yoffset = fb->vi.yres;
79 if (ioctl(fb->fd, FBIOPUT_VSCREENINFO, &fb->vi) < 0)
80 perror("Active fb swap failed");
82 fb->displayed_buffer = n;
85 static gr_surface fbdev_init(gr_backend *backend) {
87 size_t bufsize_for_mmap;
90 fbdev_common *fb = (fbdev_common *)backend->data;
92 if (!fbdev_init_common(backend))
95 nr_buffer = fb->vi.yres_virtual / fb->vi.yres;
96 printf("Frame buffer nr = %d\n", nr_buffer);
98 bufsize = fb->fi.line_length * fb->vi.yres;
99 //TODO : Based on Kernel code, following code is right.
100 // : However, it is strange because of bufsize > bufsize_for_mmap
101 // : It should be re-checked later with other kernel's framebuffer.
102 bufsize_for_mmap = fb->vi.xres * fb->vi.yres * fb->vi.bits_per_pixel / 8;
104 fb->gr_framebuffer[0].data = mmap(0, bufsize_for_mmap * nr_buffer,
105 PROT_READ | PROT_WRITE, MAP_SHARED,
108 if (fb->gr_framebuffer[0].data == MAP_FAILED) {
109 perror("Failed to mmap video memory");
114 fb->gr_framebuffer[1].data = fb->gr_framebuffer[0].data + bufsize;
115 gr_fill_alpha(&fb->gr_framebuffer[0]);
116 memcpy(fb->gr_framebuffer[1].data, fb->gr_framebuffer[0].data,
118 set_displayed_framebuffer(fb, 0);
120 printf("Framebuffer: %dx%d, %d BPP\n", fb->gr_draw->width,
121 fb->gr_draw->height, fb->vi.bits_per_pixel);
123 fbdev_blank(backend, true);
124 fbdev_blank(backend, false);
128 static gr_surface fbdev_flip(gr_backend *backend) {
129 fbdev_common *fb = (fbdev_common *)backend->data;
131 /* Change gr_draw to point to the buffer currently displayed,
132 * then flip the driver so we're displaying the other buffer
134 fb->gr_draw = fb->gr_framebuffer + fb->displayed_buffer;
135 set_displayed_framebuffer(fb, 1 - fb->displayed_buffer);
139 static bool fbdev_exit(gr_backend *backend) {
140 fbdev_common *fb = (fbdev_common *)backend->data;
141 size_t bufsize = fb->vi.xres * fb->vi.yres * fb->vi.bits_per_pixel / 8;
143 /* Unmap double buffer */
144 if (fb->gr_framebuffer[0].data &&
145 munmap(fb->gr_framebuffer[0].data, bufsize * 2) < 0) {
146 perror("Failed to unmmap video memory");
150 return fbdev_exit_common(backend);