Home | History | Annotate | Download | only in gralloc
      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 	if (dev == NULL)
    475 	{
    476 		AERR("Error to malloc the framebuffer (%s)", strerror(errno));
    477 		gralloc_close(gralloc_device);
    478 		return -ENOMEM;
    479 	}
    480 	memset(dev, 0, sizeof(*dev));
    481 
    482 	/* initialize the procs */
    483 	dev->common.tag = HARDWARE_DEVICE_TAG;
    484 	dev->common.version = 0;
    485 	dev->common.module = const_cast<hw_module_t *>(module);
    486 	dev->common.close = fb_close;
    487 	dev->setSwapInterval = fb_set_swap_interval;
    488 	dev->post = fb_post;
    489 	dev->setUpdateRect = 0;
    490 	dev->compositionComplete = &compositionComplete;
    491 
    492 	int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3);
    493 	const_cast<uint32_t &>(dev->flags) = 0;
    494 	const_cast<uint32_t &>(dev->width) = m->info.xres;
    495 	const_cast<uint32_t &>(dev->height) = m->info.yres;
    496 	const_cast<int &>(dev->stride) = stride;
    497 #ifdef GRALLOC_16_BITS
    498 	const_cast<int &>(dev->format) = HAL_PIXEL_FORMAT_RGB_565;
    499 #else
    500 	const_cast<int &>(dev->format) = HAL_PIXEL_FORMAT_RGBA_8888;
    501 #endif
    502 	const_cast<float &>(dev->xdpi) = m->xdpi;
    503 	const_cast<float &>(dev->ydpi) = m->ydpi;
    504 	const_cast<float &>(dev->fps) = m->fps;
    505 	const_cast<int &>(dev->minSwapInterval) = 0;
    506 	const_cast<int &>(dev->maxSwapInterval) = 1;
    507 	*device = &dev->common;
    508 	status = 0;
    509 
    510 	MALI_IGNORE(name);
    511 	return status;
    512 }
    513