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