1 /* 2 * Copyright (C) 2008 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 <sys/mman.h> 18 19 #include <dlfcn.h> 20 21 #include <cutils/ashmem.h> 22 #include <cutils/log.h> 23 24 #include <hardware/hardware.h> 25 #include <hardware/gralloc.h> 26 27 #include <fcntl.h> 28 #include <errno.h> 29 #include <sys/ioctl.h> 30 #include <string.h> 31 #include <stdlib.h> 32 33 #include <utils/Vector.h> 34 35 #include <cutils/log.h> 36 #include <cutils/atomic.h> 37 38 #if HAVE_ANDROID_OS 39 #include <linux/fb.h> 40 #endif 41 42 #include "gralloc_priv.h" 43 44 /*****************************************************************************/ 45 46 // numbers of buffers for page flipping 47 #define NUM_BUFFERS 2 48 49 struct hwc_callback_entry 50 { 51 void (*callback)(void *, private_handle_t *); 52 void *data; 53 }; 54 55 typedef android::Vector<struct hwc_callback_entry> hwc_callback_queue_t; 56 57 struct fb_context_t { 58 framebuffer_device_t device; 59 }; 60 61 /*****************************************************************************/ 62 63 static int fb_setSwapInterval(struct framebuffer_device_t* dev, 64 int interval) 65 { 66 fb_context_t* ctx = (fb_context_t*)dev; 67 if (interval < dev->minSwapInterval || interval > dev->maxSwapInterval) 68 return -EINVAL; 69 // FIXME: implement fb_setSwapInterval 70 return 0; 71 } 72 73 static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) 74 { 75 if (private_handle_t::validate(buffer) < 0) 76 return -EINVAL; 77 78 private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(buffer); 79 private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module); 80 81 hwc_callback_queue_t *queue = reinterpret_cast<hwc_callback_queue_t *>(m->queue); 82 pthread_mutex_lock(&m->queue_lock); 83 if(queue->isEmpty()) 84 pthread_mutex_unlock(&m->queue_lock); 85 else { 86 private_handle_t *hnd = private_handle_t::dynamicCast(buffer); 87 struct hwc_callback_entry entry = queue->top(); 88 queue->pop(); 89 pthread_mutex_unlock(&m->queue_lock); 90 entry.callback(entry.data, hnd); 91 } 92 93 return 0; 94 } 95 96 /*****************************************************************************/ 97 98 static int fb_close(struct hw_device_t *dev) 99 { 100 fb_context_t* ctx = (fb_context_t*)dev; 101 if (ctx) { 102 free(ctx); 103 } 104 return 0; 105 } 106 107 static void get_screen_res(const char *fbname, int32_t *xres, int32_t *yres, 108 int32_t *refresh) 109 { 110 char *path; 111 int fd; 112 char buf[128]; 113 int ret; 114 unsigned int _x, _y, _r; 115 116 asprintf(&path, "/sys/class/graphics/%s/modes", fbname); 117 if (!path) 118 goto err_asprintf; 119 fd = open(path, O_RDONLY); 120 if (fd < 0) 121 goto err_open; 122 ret = read(fd, buf, sizeof(buf)); 123 if (ret <= 0) 124 goto err_read; 125 buf[sizeof(buf)-1] = '\0'; 126 127 ret = sscanf(buf, "U:%ux%up-%u", &_x, &_y, &_r); 128 if (ret != 3) 129 goto err_sscanf; 130 131 ALOGI("Using %ux%u %uHz resolution for '%s' from modes list\n", 132 _x, _y, _r, fbname); 133 134 *xres = (int32_t)_x; 135 *yres = (int32_t)_y; 136 *refresh = (int32_t)_r; 137 138 close(fd); 139 free(path); 140 return; 141 142 err_sscanf: 143 err_read: 144 close(fd); 145 err_open: 146 free(path); 147 err_asprintf: 148 *xres = 2560; 149 *yres = 1600; 150 *refresh = 60; 151 } 152 153 int init_fb(struct private_module_t* module) 154 { 155 char const * const device_template[] = { 156 "/dev/graphics/fb%u", 157 "/dev/fb%u", 158 NULL 159 }; 160 161 int fd = -1; 162 int i = 0; 163 char name[64]; 164 165 fd = open("/dev/graphics/fb0", O_RDWR); 166 if (fd < 0) { 167 ALOGE("/dev/graphics/fb0 Open fail"); 168 return -errno; 169 } 170 171 struct fb_fix_screeninfo finfo; 172 if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) { 173 ALOGE("Fail to get FB Screen Info"); 174 return -errno; 175 } 176 177 struct fb_var_screeninfo info; 178 if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) { 179 ALOGE("First, Fail to get FB VScreen Info"); 180 return -errno; 181 } 182 183 int32_t refreshRate; 184 get_screen_res("fb0", &module->xres, &module->yres, &refreshRate); 185 if (refreshRate == 0) 186 refreshRate = 60; /* 60 Hz */ 187 188 float xdpi = (module->xres * 25.4f) / info.width; 189 float ydpi = (module->yres * 25.4f) / info.height; 190 191 ALOGI("using (id=%s)\n" 192 "xres = %d px\n" 193 "yres = %d px\n" 194 "width = %d mm (%f dpi)\n" 195 "height = %d mm (%f dpi)\n" 196 "refresh rate = %.2f Hz\n", 197 finfo.id, module->xres, module->yres, info.width, xdpi, info.height, 198 ydpi, (float)refreshRate); 199 200 module->line_length = module->xres * 4; 201 module->xdpi = xdpi; 202 module->ydpi = ydpi; 203 module->fps = (float)refreshRate; 204 205 return 0; 206 } 207 208 int fb_device_open(hw_module_t const* module, const char* name, 209 hw_device_t** device) 210 { 211 int status = -EINVAL; 212 #ifdef GRALLOC_16_BITS 213 int bits_per_pixel = 16; 214 int format = HAL_PIXEL_FORMAT_RGB_565; 215 #else 216 int bits_per_pixel = 32; 217 int format = HAL_PIXEL_FORMAT_RGBA_8888; 218 #endif 219 220 alloc_device_t* gralloc_device; 221 status = gralloc_open(module, &gralloc_device); 222 if (status < 0) { 223 ALOGE("Fail to Open gralloc device"); 224 return status; 225 } 226 227 framebuffer_device_t *dev = (framebuffer_device_t *)malloc(sizeof(framebuffer_device_t)); 228 if (dev == NULL) { 229 ALOGE("Failed to allocate memory for dev"); 230 gralloc_close(gralloc_device); 231 return status; 232 } 233 234 private_module_t* m = (private_module_t*)module; 235 status = init_fb(m); 236 if (status < 0) { 237 ALOGE("Fail to init framebuffer"); 238 free(dev); 239 gralloc_close(gralloc_device); 240 return status; 241 } 242 243 /* initialize our state here */ 244 memset(dev, 0, sizeof(*dev)); 245 246 /* initialize the procs */ 247 dev->common.tag = HARDWARE_DEVICE_TAG; 248 dev->common.version = 0; 249 dev->common.module = const_cast<hw_module_t*>(module); 250 dev->common.close = fb_close; 251 dev->setSwapInterval = 0; 252 dev->post = fb_post; 253 dev->setUpdateRect = 0; 254 dev->compositionComplete = 0; 255 m->queue = new hwc_callback_queue_t; 256 pthread_mutex_init(&m->queue_lock, NULL); 257 258 int stride = m->line_length / (bits_per_pixel >> 3); 259 const_cast<uint32_t&>(dev->flags) = 0; 260 const_cast<uint32_t&>(dev->width) = m->xres; 261 const_cast<uint32_t&>(dev->height) = m->yres; 262 const_cast<int&>(dev->stride) = stride; 263 const_cast<int&>(dev->format) = format; 264 const_cast<float&>(dev->xdpi) = m->xdpi; 265 const_cast<float&>(dev->ydpi) = m->ydpi; 266 const_cast<float&>(dev->fps) = m->fps; 267 const_cast<int&>(dev->minSwapInterval) = 1; 268 const_cast<int&>(dev->maxSwapInterval) = 1; 269 *device = &dev->common; 270 status = 0; 271 272 return status; 273 } 274