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