1 /* 2 * Copyright (C) 2010 ARM Limited. All rights reserved. 3 * 4 * Copyright (C) 2008 The Android Open Source Project 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 #include <string.h> 20 #include <errno.h> 21 #include <fcntl.h> 22 #include <sys/ioctl.h> 23 #include <linux/fb.h> 24 #include <stdlib.h> 25 #include <cutils/log.h> 26 #include <cutils/atomic.h> 27 #include <hardware/hardware.h> 28 #include <hardware/gralloc.h> 29 30 #include <GLES/gl.h> 31 32 #ifdef MALI_VSYNC_EVENT_REPORT_ENABLE 33 #include "gralloc_vsync_report.h" 34 #endif 35 36 #include "alloc_device.h" 37 #include "gralloc_priv.h" 38 #include "gralloc_helper.h" 39 40 // numbers of buffers for page flipping 41 #define NUM_BUFFERS NUM_FB_BUFFERS 42 43 static int swapInterval = 1; 44 45 enum 46 { 47 PAGE_FLIP = 0x00000001, 48 }; 49 50 51 static int fb_set_swap_interval(struct framebuffer_device_t *dev, int interval) 52 { 53 if (interval < dev->minSwapInterval) 54 { 55 interval = dev->minSwapInterval; 56 } 57 else if (interval > dev->maxSwapInterval) 58 { 59 interval = dev->maxSwapInterval; 60 } 61 62 swapInterval = interval; 63 64 return 0; 65 } 66 67 static int fb_post(struct framebuffer_device_t *dev, buffer_handle_t buffer) 68 { 69 if (private_handle_t::validate(buffer) < 0) 70 { 71 return -EINVAL; 72 } 73 74 private_handle_t const *hnd = reinterpret_cast<private_handle_t const *>(buffer); 75 private_module_t *m = reinterpret_cast<private_module_t *>(dev->common.module); 76 77 if (m->currentBuffer) 78 { 79 m->base.unlock(&m->base, m->currentBuffer); 80 m->currentBuffer = 0; 81 } 82 83 if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) 84 { 85 m->base.lock(&m->base, buffer, private_module_t::PRIV_USAGE_LOCKED_FOR_POST, 86 0, 0, m->info.xres, m->info.yres, NULL); 87 88 const size_t offset = (uintptr_t)hnd->base - (uintptr_t)m->framebuffer->base; 89 int interrupt; 90 m->info.activate = FB_ACTIVATE_VBL; 91 m->info.yoffset = offset / m->finfo.line_length; 92 93 #ifdef STANDARD_LINUX_SCREEN 94 #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) 95 #define S3CFB_SET_VSYNC_INT _IOW('F', 206, unsigned int) 96 97 int fbdev_fd = m->framebuffer->shallow_fbdev_fd; 98 99 if (ioctl(fbdev_fd, FBIOPAN_DISPLAY, &m->info) == -1) 100 { 101 AERR("FBIOPAN_DISPLAY failed for fd: %d", fbdev_fd); 102 m->base.unlock(&m->base, buffer); 103 return 0; 104 } 105 106 if (swapInterval == 1) 107 { 108 // enable VSYNC 109 interrupt = 1; 110 111 if (ioctl(fbdev_fd, S3CFB_SET_VSYNC_INT, &interrupt) < 0) 112 { 113 // AERR("S3CFB_SET_VSYNC_INT enable failed for fd: %d", fbdev_fd); 114 return 0; 115 } 116 117 // wait for VSYNC 118 #ifdef MALI_VSYNC_EVENT_REPORT_ENABLE 119 gralloc_mali_vsync_report(MALI_VSYNC_EVENT_BEGIN_WAIT); 120 #endif 121 int crtc = 0; 122 123 if (ioctl(fbdev_fd, FBIO_WAITFORVSYNC, &crtc) < 0) 124 { 125 AERR("FBIO_WAITFORVSYNC failed for fd: %d", fbdev_fd); 126 #ifdef MALI_VSYNC_EVENT_REPORT_ENABLE 127 gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT); 128 #endif 129 return 0; 130 } 131 132 #ifdef MALI_VSYNC_EVENT_REPORT_ENABLE 133 gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT); 134 #endif 135 // disable VSYNC 136 interrupt = 0; 137 138 if (ioctl(fbdev_fd, S3CFB_SET_VSYNC_INT, &interrupt) < 0) 139 { 140 AERR("S3CFB_SET_VSYNC_INT disable failed for fd: %d", fbdev_fd); 141 return 0; 142 } 143 } 144 145 #else 146 /*Standard Android way*/ 147 #ifdef MALI_VSYNC_EVENT_REPORT_ENABLE 148 gralloc_mali_vsync_report(MALI_VSYNC_EVENT_BEGIN_WAIT); 149 #endif 150 151 if (ioctl(fbdev_fd, FBIOPUT_VSCREENINFO, &m->info) == -1) 152 { 153 AERR("FBIOPUT_VSCREENINFO failed for fd: %d", fbdev_fd); 154 #ifdef MALI_VSYNC_EVENT_REPORT_ENABLE 155 gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT); 156 #endif 157 m->base.unlock(&m->base, buffer); 158 return -errno; 159 } 160 161 #ifdef MALI_VSYNC_EVENT_REPORT_ENABLE 162 gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT); 163 #endif 164 #endif 165 166 m->currentBuffer = buffer; 167 } 168 else 169 { 170 void *fb_vaddr; 171 void *buffer_vaddr; 172 173 m->base.lock(&m->base, m->framebuffer, GRALLOC_USAGE_SW_WRITE_RARELY, 174 0, 0, m->info.xres, m->info.yres, &fb_vaddr); 175 176 m->base.lock(&m->base, buffer, GRALLOC_USAGE_SW_READ_RARELY, 177 0, 0, m->info.xres, m->info.yres, &buffer_vaddr); 178 179 memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres); 180 181 m->base.unlock(&m->base, buffer); 182 m->base.unlock(&m->base, m->framebuffer); 183 } 184 185 return 0; 186 } 187 188 int init_frame_buffer_locked(struct private_module_t *module) 189 { 190 if (module->framebuffer) 191 { 192 return 0; // Nothing to do, already initialized 193 } 194 195 char const *const device_template[] = 196 { 197 "/dev/graphics/fb%u", 198 "/dev/fb%u", 199 NULL 200 }; 201 202 int fd = -1; 203 int i = 0; 204 char name[64]; 205 206 while ((fd == -1) && device_template[i]) 207 { 208 snprintf(name, 64, device_template[i], 0); 209 fd = open(name, O_RDWR, 0); 210 i++; 211 } 212 213 if (fd < 0) 214 { 215 return -errno; 216 } 217 218 struct fb_fix_screeninfo finfo; 219 220 if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) 221 { 222 return -errno; 223 } 224 225 struct fb_var_screeninfo info; 226 227 if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) 228 { 229 return -errno; 230 } 231 232 info.reserved[0] = 0; 233 info.reserved[1] = 0; 234 info.reserved[2] = 0; 235 info.xoffset = 0; 236 info.yoffset = 0; 237 info.activate = FB_ACTIVATE_NOW; 238 239 #ifdef GRALLOC_16_BITS 240 /* 241 * Explicitly request 5/6/5 242 */ 243 info.bits_per_pixel = 16; 244 info.red.offset = 11; 245 info.red.length = 5; 246 info.green.offset = 5; 247 info.green.length = 6; 248 info.blue.offset = 0; 249 info.blue.length = 5; 250 info.transp.offset = 0; 251 info.transp.length = 0; 252 #else 253 /* 254 * Explicitly request 8/8/8 255 */ 256 info.bits_per_pixel = 32; 257 info.red.offset = 0; 258 info.red.length = 8; 259 info.green.offset = 8; 260 info.green.length = 8; 261 info.blue.offset = 16; 262 info.blue.length = 8; 263 info.transp.offset = 24; 264 info.transp.length = 8; 265 #endif 266 267 /* 268 * Request NUM_BUFFERS screens (at lest 2 for page flipping) 269 */ 270 info.yres_virtual = info.yres * NUM_BUFFERS; 271 272 uint32_t flags = PAGE_FLIP; 273 274 if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) 275 { 276 info.yres_virtual = info.yres; 277 flags &= ~PAGE_FLIP; 278 AWAR("FBIOPUT_VSCREENINFO failed, page flipping not supported fd: %d", fd); 279 } 280 281 if (info.yres_virtual < info.yres * 2) 282 { 283 // we need at least 2 for page-flipping 284 info.yres_virtual = info.yres; 285 flags &= ~PAGE_FLIP; 286 AWAR("page flipping not supported (yres_virtual=%d, requested=%d)", info.yres_virtual, info.yres * 2); 287 } 288 289 if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) 290 { 291 return -errno; 292 } 293 294 int refreshRate = 0; 295 296 if (info.pixclock > 0) 297 { 298 refreshRate = 1000000000000000LLU / 299 ( 300 uint64_t(info.upper_margin + info.lower_margin + info.yres + info.hsync_len) 301 * (info.left_margin + info.right_margin + info.xres + info.vsync_len) 302 * info.pixclock 303 ); 304 } 305 else 306 { 307 AWAR("fbdev pixclock is zero for fd: %d", fd); 308 } 309 310 if (refreshRate == 0) 311 { 312 refreshRate = 60 * 1000; // 60 Hz 313 } 314 315 if (int(info.width) <= 0 || int(info.height) <= 0) 316 { 317 // the driver doesn't return that information 318 // default to 160 dpi 319 info.width = ((info.xres * 25.4f) / 160.0f + 0.5f); 320 info.height = ((info.yres * 25.4f) / 160.0f + 0.5f); 321 } 322 323 float xdpi = (info.xres * 25.4f) / info.width; 324 float ydpi = (info.yres * 25.4f) / info.height; 325 float fps = refreshRate / 1000.0f; 326 327 AINF("using (fd=%d)\n" 328 "id = %s\n" 329 "xres = %d px\n" 330 "yres = %d px\n" 331 "xres_virtual = %d px\n" 332 "yres_virtual = %d px\n" 333 "bpp = %d\n" 334 "r = %2u:%u\n" 335 "g = %2u:%u\n" 336 "b = %2u:%u\n", 337 fd, 338 finfo.id, 339 info.xres, 340 info.yres, 341 info.xres_virtual, 342 info.yres_virtual, 343 info.bits_per_pixel, 344 info.red.offset, info.red.length, 345 info.green.offset, info.green.length, 346 info.blue.offset, info.blue.length); 347 348 AINF("width = %d mm (%f dpi)\n" 349 "height = %d mm (%f dpi)\n" 350 "refresh rate = %.2f Hz\n", 351 info.width, xdpi, 352 info.height, ydpi, 353 fps); 354 355 if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) 356 { 357 return -errno; 358 } 359 360 if (finfo.smem_len <= 0) 361 { 362 return -errno; 363 } 364 365 module->flags = flags; 366 module->info = info; 367 module->finfo = finfo; 368 module->xdpi = xdpi; 369 module->ydpi = ydpi; 370 module->fps = fps; 371 372 /* 373 * map the framebuffer 374 */ 375 size_t fbSize = round_up_to_page_size(finfo.line_length * info.yres_virtual); 376 void *vaddr = mmap(0, fbSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 377 378 if (vaddr == MAP_FAILED) 379 { 380 AERR("Error mapping the framebuffer (%s)", strerror(errno)); 381 return -errno; 382 } 383 384 memset(vaddr, 0, fbSize); 385 386 // Create a "fake" buffer object for the entire frame buffer memory, and store it in the module 387 module->framebuffer = new private_handle_t(private_handle_t::PRIV_FLAGS_FRAMEBUFFER, 0, fbSize, vaddr, 388 0, fd, 0); 389 390 module->numBuffers = info.yres_virtual / info.yres; 391 module->bufferMask = 0; 392 393 #if GRALLOC_ARM_UMP_MODULE 394 #ifdef IOCTL_GET_FB_UMP_SECURE_ID 395 ioctl(fd, IOCTL_GET_FB_UMP_SECURE_ID, &module->framebuffer->ump_id); 396 #endif 397 398 if ((int)UMP_INVALID_SECURE_ID != module->framebuffer->ump_id) 399 { 400 AINF("framebuffer accessed with UMP secure ID %i\n", module->framebuffer->ump_id); 401 } 402 403 #endif 404 405 return 0; 406 } 407 408 static int init_frame_buffer(struct private_module_t *module) 409 { 410 pthread_mutex_lock(&module->lock); 411 int err = init_frame_buffer_locked(module); 412 pthread_mutex_unlock(&module->lock); 413 return err; 414 } 415 416 static int fb_close(struct hw_device_t *device) 417 { 418 framebuffer_device_t *dev = reinterpret_cast<framebuffer_device_t *>(device); 419 420 if (dev) 421 { 422 #if GRALLOC_ARM_UMP_MODULE 423 ump_close(); 424 #endif 425 free(dev); 426 } 427 428 return 0; 429 } 430 431 int compositionComplete(struct framebuffer_device_t *dev) 432 { 433 MALI_IGNORE(dev); 434 /* By doing a finish here we force the GL driver to start rendering 435 all the drawcalls up to this point, and to wait for the rendering to be complete.*/ 436 glFinish(); 437 /* The rendering of the backbuffer is now completed. 438 When SurfaceFlinger later does a call to eglSwapBuffer(), the swap will be done 439 synchronously in the same thread, and not asynchronoulsy in a background thread later. 440 The SurfaceFlinger requires this behaviour since it releases the lock on all the 441 SourceBuffers (Layers) after the compositionComplete() function returns. 442 However this "bad" behaviour by SurfaceFlinger should not affect performance, 443 since the Applications that render the SourceBuffers (Layers) still get the 444 full renderpipeline using asynchronous rendering. So they perform at maximum speed, 445 and because of their complexity compared to the Surface flinger jobs, the Surface flinger 446 is normally faster even if it does everyhing synchronous and serial. 447 */ 448 return 0; 449 } 450 451 int framebuffer_device_open(hw_module_t const *module, const char *name, hw_device_t **device) 452 { 453 int status = -EINVAL; 454 455 alloc_device_t *gralloc_device; 456 status = gralloc_open(module, &gralloc_device); 457 458 if (status < 0) 459 { 460 return status; 461 } 462 463 private_module_t *m = (private_module_t *)module; 464 status = init_frame_buffer(m); 465 466 if (status < 0) 467 { 468 gralloc_close(gralloc_device); 469 return status; 470 } 471 472 /* initialize our state here */ 473 framebuffer_device_t *dev = (framebuffer_device_t *)malloc(sizeof(framebuffer_device_t)); 474 memset(dev, 0, sizeof(*dev)); 475 476 /* initialize the procs */ 477 dev->common.tag = HARDWARE_DEVICE_TAG; 478 dev->common.version = 0; 479 dev->common.module = const_cast<hw_module_t *>(module); 480 dev->common.close = fb_close; 481 dev->setSwapInterval = fb_set_swap_interval; 482 dev->post = fb_post; 483 dev->setUpdateRect = 0; 484 dev->compositionComplete = &compositionComplete; 485 486 int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3); 487 const_cast<uint32_t &>(dev->flags) = 0; 488 const_cast<uint32_t &>(dev->width) = m->info.xres; 489 const_cast<uint32_t &>(dev->height) = m->info.yres; 490 const_cast<int &>(dev->stride) = stride; 491 #ifdef GRALLOC_16_BITS 492 const_cast<int &>(dev->format) = HAL_PIXEL_FORMAT_RGB_565; 493 #else 494 const_cast<int &>(dev->format) = HAL_PIXEL_FORMAT_RGBA_8888; 495 #endif 496 const_cast<float &>(dev->xdpi) = m->xdpi; 497 const_cast<float &>(dev->ydpi) = m->ydpi; 498 const_cast<float &>(dev->fps) = m->fps; 499 const_cast<int &>(dev->minSwapInterval) = 0; 500 const_cast<int &>(dev->maxSwapInterval) = 1; 501 *device = &dev->common; 502 status = 0; 503 504 MALI_IGNORE(name); 505 return status; 506 } 507