Home | History | Annotate | Download | only in gralloc960
      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