Home | History | Annotate | Download | only in gralloc960
      1 /*
      2  * Copyright (C) 2010-2017 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 <log/log.h>
     27 #include <cutils/atomic.h>
     28 #include <hardware/hardware.h>
     29 #include <hardware/fb.h>
     30 
     31 #include <GLES/gl.h>
     32 
     33 #if GRALLOC_USE_GRALLOC1_API == 1
     34 #include <hardware/gralloc1.h>
     35 #else
     36 #include <hardware/gralloc.h>
     37 #endif
     38 
     39 #include "mali_gralloc_module.h"
     40 #include "mali_gralloc_private_interface_types.h"
     41 #include "mali_gralloc_buffer.h"
     42 #include "gralloc_helper.h"
     43 #include "gralloc_vsync.h"
     44 #include "mali_gralloc_bufferaccess.h"
     45 #include "mali_gralloc_ion.h"
     46 
     47 #define STANDARD_LINUX_SCREEN
     48 
     49 // numbers of buffers for page flipping
     50 #define NUM_BUFFERS NUM_FB_BUFFERS
     51 
     52 enum
     53 {
     54 	PAGE_FLIP = 0x00000001,
     55 };
     56 
     57 static int fb_set_swap_interval(struct framebuffer_device_t *dev, int interval)
     58 {
     59 	if (interval < dev->minSwapInterval)
     60 	{
     61 		interval = dev->minSwapInterval;
     62 	}
     63 	else if (interval > dev->maxSwapInterval)
     64 	{
     65 		interval = dev->maxSwapInterval;
     66 	}
     67 
     68 	private_module_t *m = reinterpret_cast<private_module_t *>(dev->common.module);
     69 	m->swapInterval = interval;
     70 
     71 	if (0 == interval)
     72 	{
     73 		gralloc_vsync_disable(dev);
     74 	}
     75 	else
     76 	{
     77 		gralloc_vsync_enable(dev);
     78 	}
     79 
     80 	return 0;
     81 }
     82 
     83 static int fb_post(struct framebuffer_device_t *dev, buffer_handle_t buffer)
     84 {
     85 	if (private_handle_t::validate(buffer) < 0)
     86 	{
     87 		return -EINVAL;
     88 	}
     89 
     90 	private_handle_t const *hnd = reinterpret_cast<private_handle_t const *>(buffer);
     91 	private_module_t *m = reinterpret_cast<private_module_t *>(dev->common.module);
     92 
     93 	if (m->currentBuffer)
     94 	{
     95 		mali_gralloc_unlock(m, m->currentBuffer);
     96 		m->currentBuffer = 0;
     97 	}
     98 
     99 	if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)
    100 	{
    101 		mali_gralloc_lock(m, buffer, private_module_t::PRIV_USAGE_LOCKED_FOR_POST, -1, -1, -1, -1, NULL);
    102 
    103 		int interrupt;
    104 		m->info.activate = FB_ACTIVATE_VBL;
    105 		m->info.yoffset = hnd->offset / m->finfo.line_length;
    106 
    107 #ifdef STANDARD_LINUX_SCREEN
    108 
    109 		if (ioctl(m->framebuffer->fd, FBIOPAN_DISPLAY, &m->info) == -1)
    110 		{
    111 			AERR("FBIOPAN_DISPLAY failed for fd: %d", m->framebuffer->fd);
    112 			mali_gralloc_unlock(m, buffer);
    113 			return -errno;
    114 		}
    115 
    116 #else /*Standard Android way*/
    117 
    118 		if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1)
    119 		{
    120 			AERR("FBIOPUT_VSCREENINFO failed for fd: %d", m->framebuffer->fd);
    121 			mali_gralloc_unlock(m, buffer);
    122 			return -errno;
    123 		}
    124 
    125 #endif
    126 
    127 		if (0 != gralloc_wait_for_vsync(dev))
    128 		{
    129 			AERR("Gralloc wait for vsync failed for fd: %d", m->framebuffer->fd);
    130 			mali_gralloc_unlock(m, buffer);
    131 			return -errno;
    132 		}
    133 
    134 		m->currentBuffer = buffer;
    135 	}
    136 	else
    137 	{
    138 		void *fb_vaddr;
    139 		void *buffer_vaddr;
    140 
    141 		mali_gralloc_lock(m, m->framebuffer, GRALLOC_USAGE_SW_WRITE_RARELY, -1, -1, -1, -1, &fb_vaddr);
    142 
    143 		mali_gralloc_lock(m, buffer, GRALLOC_USAGE_SW_READ_RARELY, -1, -1, -1, -1, &buffer_vaddr);
    144 
    145 		// If buffer's alignment match framebuffer alignment we can do a direct copy.
    146 		// If not we must fallback to do an aligned copy of each line.
    147 		if (hnd->byte_stride == (int)m->finfo.line_length)
    148 		{
    149 			memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres);
    150 		}
    151 		else
    152 		{
    153 			uintptr_t fb_offset = 0;
    154 			uintptr_t buffer_offset = 0;
    155 			unsigned int i;
    156 
    157 			for (i = 0; i < m->info.yres; i++)
    158 			{
    159 				memcpy((void *)((uintptr_t)fb_vaddr + fb_offset), (void *)((uintptr_t)buffer_vaddr + buffer_offset),
    160 				       m->finfo.line_length);
    161 
    162 				fb_offset += m->finfo.line_length;
    163 				buffer_offset += hnd->byte_stride;
    164 			}
    165 		}
    166 
    167 		mali_gralloc_unlock(m, buffer);
    168 		mali_gralloc_unlock(m, m->framebuffer);
    169 	}
    170 
    171 	return 0;
    172 }
    173 
    174 static int init_frame_buffer_locked(struct private_module_t *module)
    175 {
    176 	if (module->framebuffer)
    177 	{
    178 		return 0; // Nothing to do, already initialized
    179 	}
    180 
    181 	char const *const device_template[] = { "/dev/graphics/fb%u", "/dev/fb%u", NULL };
    182 
    183 	int fd = -1;
    184 	int i = 0;
    185 	char name[64];
    186 
    187 	while ((fd == -1) && device_template[i])
    188 	{
    189 		snprintf(name, 64, device_template[i], 0);
    190 		fd = open(name, O_RDWR, 0);
    191 		i++;
    192 	}
    193 
    194 	if (fd < 0)
    195 	{
    196 		return -errno;
    197 	}
    198 
    199 	struct fb_fix_screeninfo finfo;
    200 
    201 	if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
    202 	{
    203 		return -errno;
    204 	}
    205 
    206 	struct fb_var_screeninfo info;
    207 
    208 	if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
    209 	{
    210 		return -errno;
    211 	}
    212 
    213 	info.reserved[0] = 0;
    214 	info.reserved[1] = 0;
    215 	info.reserved[2] = 0;
    216 	info.xoffset = 0;
    217 	info.yoffset = 0;
    218 	info.activate = FB_ACTIVATE_NOW;
    219 
    220 #ifdef GRALLOC_16_BITS
    221 	/*
    222 	 * Explicitly request 5/6/5
    223 	 */
    224 	info.bits_per_pixel = 16;
    225 	info.red.offset = 11;
    226 	info.red.length = 5;
    227 	info.green.offset = 5;
    228 	info.green.length = 6;
    229 	info.blue.offset = 0;
    230 	info.blue.length = 5;
    231 	info.transp.offset = 0;
    232 	info.transp.length = 0;
    233 #else
    234 	/*
    235 	 * Explicitly request 8/8/8
    236 	 */
    237 	info.bits_per_pixel = 32;
    238 	info.red.offset = 16;
    239 	info.red.length = 8;
    240 	info.green.offset = 8;
    241 	info.green.length = 8;
    242 	info.blue.offset = 0;
    243 	info.blue.length = 8;
    244 	info.transp.offset = 0;
    245 	info.transp.length = 0;
    246 #endif
    247 
    248 	/*
    249 	 * Request NUM_BUFFERS screens (at lest 2 for page flipping)
    250 	 */
    251 	info.yres_virtual = info.yres * NUM_BUFFERS;
    252 
    253 	uint32_t flags = PAGE_FLIP;
    254 
    255 	if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1)
    256 	{
    257 		info.yres_virtual = info.yres;
    258 		flags &= ~PAGE_FLIP;
    259 		AWAR("FBIOPUT_VSCREENINFO failed, page flipping not supported fd: %d", fd);
    260 	}
    261 
    262 	if (info.yres_virtual < info.yres * 2)
    263 	{
    264 		// we need at least 2 for page-flipping
    265 		info.yres_virtual = info.yres;
    266 		flags &= ~PAGE_FLIP;
    267 		AWAR("page flipping not supported (yres_virtual=%d, requested=%d)", info.yres_virtual, info.yres * 2);
    268 	}
    269 
    270 	if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
    271 	{
    272 		return -errno;
    273 	}
    274 
    275 	int refreshRate = 0;
    276 
    277 	if (info.pixclock > 0)
    278 	{
    279 		refreshRate =
    280 		    1000000000000000LLU / (uint64_t(info.upper_margin + info.lower_margin + info.yres + info.hsync_len) *
    281 		                           (info.left_margin + info.right_margin + info.xres + info.vsync_len) * info.pixclock);
    282 	}
    283 	else
    284 	{
    285 		AWAR("fbdev pixclock is zero for fd: %d", fd);
    286 	}
    287 
    288 	if (refreshRate == 0)
    289 	{
    290 		refreshRate = 60 * 1000; // 60 Hz
    291 	}
    292 
    293 	if (int(info.width) <= 0 || int(info.height) <= 0)
    294 	{
    295 		// the driver doesn't return that information
    296 		// default to 160 dpi
    297 		info.width = ((info.xres * 25.4f) / 160.0f + 0.5f);
    298 		info.height = ((info.yres * 25.4f) / 160.0f + 0.5f);
    299 	}
    300 
    301 	float xdpi = (info.xres * 25.4f) / info.width;
    302 	float ydpi = (info.yres * 25.4f) / info.height;
    303 	float fps = refreshRate / 1000.0f;
    304 
    305 	AINF("using (fd=%d)\n"
    306 	     "id           = %s\n"
    307 	     "xres         = %d px\n"
    308 	     "yres         = %d px\n"
    309 	     "xres_virtual = %d px\n"
    310 	     "yres_virtual = %d px\n"
    311 	     "bpp          = %d\n"
    312 	     "r            = %2u:%u\n"
    313 	     "g            = %2u:%u\n"
    314 	     "b            = %2u:%u\n",
    315 	     fd, finfo.id, info.xres, info.yres, info.xres_virtual, info.yres_virtual, info.bits_per_pixel, info.red.offset,
    316 	     info.red.length, info.green.offset, info.green.length, info.blue.offset, info.blue.length);
    317 
    318 	AINF("width        = %d mm (%f dpi)\n"
    319 	     "height       = %d mm (%f dpi)\n"
    320 	     "refresh rate = %.2f Hz\n",
    321 	     info.width, xdpi, info.height, ydpi, fps);
    322 
    323 	if (0 == strncmp(finfo.id, "CLCD FB", 7))
    324 	{
    325 		module->dpy_type = MALI_DPY_TYPE_CLCD;
    326 	}
    327 	else if (0 == strncmp(finfo.id, "ARM Mali HDLCD", 14))
    328 	{
    329 		module->dpy_type = MALI_DPY_TYPE_HDLCD;
    330 	}
    331 	else if (0 == strncmp(finfo.id, "ARM HDLCD Control", 16))
    332 	{
    333 		module->dpy_type = MALI_DPY_TYPE_HDLCD;
    334 	}
    335 	else
    336 	{
    337 		module->dpy_type = MALI_DPY_TYPE_UNKNOWN;
    338 	}
    339 
    340 	if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
    341 	{
    342 		return -errno;
    343 	}
    344 
    345 	if (finfo.smem_len <= 0)
    346 	{
    347 		return -errno;
    348 	}
    349 
    350 	module->flags = flags;
    351 	module->info = info;
    352 	module->finfo = finfo;
    353 	module->xdpi = xdpi;
    354 	module->ydpi = ydpi;
    355 	module->fps = fps;
    356 	module->swapInterval = 1;
    357 
    358 	/*
    359 	 * map the framebuffer
    360 	 */
    361 	size_t fbSize = round_up_to_page_size(finfo.line_length * info.yres_virtual);
    362 	void *vaddr = mmap(0, fbSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    363 
    364 	if (vaddr == MAP_FAILED)
    365 	{
    366 		AERR("Error mapping the framebuffer (%s)", strerror(errno));
    367 		return -errno;
    368 	}
    369 
    370 	memset(vaddr, 0, fbSize);
    371 
    372 	// Create a "fake" buffer object for the entire frame buffer memory, and store it in the module
    373 	module->framebuffer = new private_handle_t(private_handle_t::PRIV_FLAGS_FRAMEBUFFER, fbSize, vaddr,
    374 	                                           GRALLOC_USAGE_HW_FB, GRALLOC_USAGE_HW_FB, dup(fd), 0);
    375 
    376 	module->numBuffers = info.yres_virtual / info.yres;
    377 	module->bufferMask = 0;
    378 
    379 	return 0;
    380 }
    381 
    382 static int init_frame_buffer(struct private_module_t *module)
    383 {
    384 	pthread_mutex_lock(&module->lock);
    385 	int err = init_frame_buffer_locked(module);
    386 	pthread_mutex_unlock(&module->lock);
    387 	return err;
    388 }
    389 
    390 static int fb_close(struct hw_device_t *device)
    391 {
    392 	framebuffer_device_t *dev = reinterpret_cast<framebuffer_device_t *>(device);
    393 
    394 	if (dev)
    395 	{
    396 		free(dev);
    397 	}
    398 
    399 	return 0;
    400 }
    401 
    402 static int fb_alloc_framebuffer_dmabuf(private_module_t *m, private_handle_t *hnd)
    403 {
    404 	struct fb_dmabuf_export fb_dma_buf;
    405 	int res;
    406 	res = ioctl(m->framebuffer->fd, FBIOGET_DMABUF, &fb_dma_buf);
    407 
    408 	if (res == 0)
    409 	{
    410 		hnd->share_fd = fb_dma_buf.fd;
    411 		return 0;
    412 	}
    413 	else
    414 	{
    415 		AINF("FBIOGET_DMABUF ioctl failed(%d). See gralloc_priv.h and the integration manual for vendor framebuffer "
    416 		     "integration",
    417 		     res);
    418 		return -1;
    419 	}
    420 }
    421 
    422 static int fb_alloc_from_ion_module(mali_gralloc_module *m, size_t buffer_size, uint64_t consumer_usage,
    423                                     uint64_t producer_usage, buffer_handle_t *pHandle)
    424 {
    425 	buffer_descriptor_t fb_buffer_descriptor;
    426 	gralloc_buffer_descriptor_t gralloc_buffer_descriptor[1];
    427 	bool shared = false;
    428 	int err = 0;
    429 
    430 	fb_buffer_descriptor.size = buffer_size;
    431 	fb_buffer_descriptor.consumer_usage = consumer_usage;
    432 	fb_buffer_descriptor.producer_usage = producer_usage;
    433 	gralloc_buffer_descriptor[0] = (gralloc_buffer_descriptor_t)(&fb_buffer_descriptor);
    434 
    435 	err = mali_gralloc_ion_allocate(m, gralloc_buffer_descriptor, 1, pHandle, &shared);
    436 
    437 	return err;
    438 }
    439 
    440 static int fb_alloc_framebuffer_locked(mali_gralloc_module *m, uint64_t consumer_usage, uint64_t producer_usage,
    441                                        buffer_handle_t *pHandle, int *stride, int *byte_stride)
    442 {
    443 	// allocate the framebuffer
    444 	if (m->framebuffer == NULL)
    445 	{
    446 		// initialize the framebuffer, the framebuffer is mapped once and forever.
    447 		int err = init_frame_buffer_locked(m);
    448 
    449 		if (err < 0)
    450 		{
    451 			return err;
    452 		}
    453 	}
    454 
    455 	uint32_t bufferMask = m->bufferMask;
    456 	const uint32_t numBuffers = m->numBuffers;
    457 	/* framebufferSize is used for allocating the handle to the framebuffer and refers
    458 	 *                 to the size of the actual framebuffer.
    459 	 * alignedFramebufferSize is used for allocating a possible internal buffer and
    460 	 *                        thus need to consider internal alignment requirements. */
    461 	const size_t framebufferSize = m->finfo.line_length * m->info.yres;
    462 	const size_t alignedFramebufferSize = GRALLOC_ALIGN(m->finfo.line_length, 64) * m->info.yres;
    463 
    464 	*stride = m->info.xres;
    465 
    466 	if (numBuffers == 1)
    467 	{
    468 		// If we have only one buffer, we never use page-flipping. Instead,
    469 		// we return a regular buffer which will be memcpy'ed to the main
    470 		// screen when post is called.
    471 		uint64_t newConsumerUsage = (consumer_usage & ~GRALLOC_USAGE_HW_FB);
    472 		uint64_t newProducerUsage = (producer_usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D;
    473 		AWAR("fallback to single buffering. Virtual Y-res too small %d", m->info.yres);
    474 		*byte_stride = GRALLOC_ALIGN(m->finfo.line_length, 64);
    475 		return fb_alloc_from_ion_module(m, alignedFramebufferSize, newConsumerUsage, newProducerUsage, pHandle);
    476 	}
    477 
    478 	if (bufferMask >= ((1LU << numBuffers) - 1))
    479 	{
    480 		// We ran out of buffers, reset bufferMask
    481 		bufferMask = 0;
    482 		m->bufferMask = 0;
    483 	}
    484 
    485 	uintptr_t framebufferVaddr = (uintptr_t)m->framebuffer->base;
    486 
    487 	// find a free slot
    488 	for (uint32_t i = 0; i < numBuffers; i++)
    489 	{
    490 		if ((bufferMask & (1LU << i)) == 0)
    491 		{
    492 			m->bufferMask |= (1LU << i);
    493 			break;
    494 		}
    495 
    496 		framebufferVaddr += framebufferSize;
    497 	}
    498 
    499 	// The entire framebuffer memory is already mapped, now create a buffer object for parts of this memory
    500 	private_handle_t *hnd = new private_handle_t(
    501 	    private_handle_t::PRIV_FLAGS_FRAMEBUFFER, framebufferSize, (void *)framebufferVaddr, consumer_usage,
    502 	    producer_usage, dup(m->framebuffer->fd), (framebufferVaddr - (uintptr_t)m->framebuffer->base));
    503 
    504 	/*
    505 	 * Perform allocator specific actions. If these fail we fall back to a regular buffer
    506 	 * which will be memcpy'ed to the main screen when fb_post is called.
    507 	 */
    508 	if (fb_alloc_framebuffer_dmabuf(m, hnd) == -1)
    509 	{
    510 		delete hnd;
    511 		uint64_t newConsumerUsage = (consumer_usage & ~GRALLOC_USAGE_HW_FB);
    512 		uint64_t newProducerUsage = (producer_usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D;
    513 		AERR("Fallback to single buffering. Unable to map framebuffer memory to handle:%p", hnd);
    514 		*byte_stride = GRALLOC_ALIGN(m->finfo.line_length, 64);
    515 		return fb_alloc_from_ion_module(m, alignedFramebufferSize, newConsumerUsage, newProducerUsage, pHandle);
    516 	}
    517 
    518 	*pHandle = hnd;
    519 	*byte_stride = m->finfo.line_length;
    520 
    521 	return 0;
    522 }
    523 
    524 int fb_alloc_framebuffer(mali_gralloc_module *m, uint64_t consumer_usage, uint64_t producer_usage,
    525                          buffer_handle_t *pHandle, int *stride, int *byte_stride)
    526 {
    527 	pthread_mutex_lock(&m->lock);
    528 	int err = fb_alloc_framebuffer_locked(m, consumer_usage, producer_usage, pHandle, stride, byte_stride);
    529 	pthread_mutex_unlock(&m->lock);
    530 	return err;
    531 }
    532 
    533 int compositionComplete(struct framebuffer_device_t *dev)
    534 {
    535 	GRALLOC_UNUSED(dev);
    536 
    537 	/* By doing a finish here we force the GL driver to start rendering
    538 	   all the drawcalls up to this point, and to wait for the rendering to be complete.*/
    539 	glFinish();
    540 	/* The rendering of the backbuffer is now completed.
    541 	   When SurfaceFlinger later does a call to eglSwapBuffer(), the swap will be done
    542 	   synchronously in the same thread, and not asynchronoulsy in a background thread later.
    543 	   The SurfaceFlinger requires this behaviour since it releases the lock on all the
    544 	   SourceBuffers (Layers) after the compositionComplete() function returns.
    545 	   However this "bad" behaviour by SurfaceFlinger should not affect performance,
    546 	   since the Applications that render the SourceBuffers (Layers) still get the
    547 	   full renderpipeline using asynchronous rendering. So they perform at maximum speed,
    548 	   and because of their complexity compared to the Surface flinger jobs, the Surface flinger
    549 	   is normally faster even if it does everyhing synchronous and serial.
    550 	   */
    551 	return 0;
    552 }
    553 
    554 int framebuffer_device_open(hw_module_t const *module, const char *name, hw_device_t **device)
    555 {
    556 	int status = -EINVAL;
    557 
    558 	GRALLOC_UNUSED(name);
    559 
    560 #if GRALLOC_USE_GRALLOC1_API == 1
    561 	gralloc1_device_t *gralloc_device;
    562 #else
    563 	alloc_device_t *gralloc_device;
    564 #endif
    565 
    566 #if DISABLE_FRAMEBUFFER_HAL == 1
    567 	AERR("Framebuffer HAL not support/disabled %s",
    568 #ifdef MALI_DISPLAY_VERSION
    569 	     "with MALI display enable");
    570 #else
    571 	     "");
    572 #endif
    573 	return -ENODEV;
    574 #endif
    575 
    576 #if GRALLOC_USE_GRALLOC1_API == 1
    577 	status = gralloc1_open(module, &gralloc_device);
    578 #else
    579 	status = gralloc_open(module, &gralloc_device);
    580 #endif
    581 
    582 	if (status < 0)
    583 	{
    584 		return status;
    585 	}
    586 
    587 	private_module_t *m = (private_module_t *)module;
    588 	status = init_frame_buffer(m);
    589 
    590 	/* malloc is used instead of 'new' to instantiate the struct framebuffer_device_t
    591 	 * C++11 spec specifies that if a class/struct has a const member,default constructor
    592 	 * is deleted. So, if 'new' is used to instantiate the class/struct, it will throw
    593 	 * error complaining about deleted constructor. Even if the struct is wrapped in a class
    594 	 * it will still try to use the base class constructor to initialize the members, resulting
    595 	 * in error 'deleted constructor'.
    596 	 * This leaves two options
    597 	 * Option 1: initialize the const members at the instantiation time. With {value1, value2 ..}
    598 	 * Which relies on the order of the members, and if members are reordered or a new member is introduced
    599 	 * it will end up assiging wrong value to members. Designated assignment as well has been removed in C++11
    600 	 * Option 2: use malloc instead of 'new' to allocate the class/struct and initialize the members in code.
    601 	 * This is the only maintainable option available.
    602 	 */
    603 
    604 	framebuffer_device_t *dev = reinterpret_cast<framebuffer_device_t *>(malloc(sizeof(framebuffer_device_t)));
    605 
    606 	/* if either or both of init_frame_buffer() and malloc failed */
    607 	if ((status < 0) || (!dev))
    608 	{
    609 #if GRALLOC_USE_GRALLOC1_API == 1
    610 		gralloc1_close(gralloc_device);
    611 #else
    612 		gralloc_close(gralloc_device);
    613 #endif
    614 		(!dev) ? (void)(status = -ENOMEM) : free(dev);
    615 		return status;
    616 	}
    617 
    618 	memset(dev, 0, sizeof(*dev));
    619 
    620 	/* initialize the procs */
    621 	dev->common.tag = HARDWARE_DEVICE_TAG;
    622 	dev->common.version = 0;
    623 	dev->common.module = const_cast<hw_module_t *>(module);
    624 	dev->common.close = fb_close;
    625 	dev->setSwapInterval = fb_set_swap_interval;
    626 	dev->post = fb_post;
    627 	dev->setUpdateRect = 0;
    628 	dev->compositionComplete = &compositionComplete;
    629 
    630 	int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3);
    631 	const_cast<uint32_t &>(dev->flags) = 0;
    632 	const_cast<uint32_t &>(dev->width) = m->info.xres;
    633 	const_cast<uint32_t &>(dev->height) = m->info.yres;
    634 	const_cast<int &>(dev->stride) = stride;
    635 #ifdef GRALLOC_16_BITS
    636 	const_cast<int &>(dev->format) = HAL_PIXEL_FORMAT_RGB_565;
    637 #else
    638 	const_cast<int &>(dev->format) = HAL_PIXEL_FORMAT_BGRA_8888;
    639 #endif
    640 	const_cast<float &>(dev->xdpi) = m->xdpi;
    641 	const_cast<float &>(dev->ydpi) = m->ydpi;
    642 	const_cast<float &>(dev->fps) = m->fps;
    643 	const_cast<int &>(dev->minSwapInterval) = 0;
    644 	const_cast<int &>(dev->maxSwapInterval) = 1;
    645 	*device = &dev->common;
    646 
    647 	gralloc_vsync_enable(dev);
    648 
    649 	return status;
    650 }
    651