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