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 
fb_set_swap_interval(struct framebuffer_device_t * dev,int interval)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 
fb_post(struct framebuffer_device_t * dev,buffer_handle_t buffer)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 
init_frame_buffer_locked(struct private_module_t * module)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 
init_frame_buffer(struct private_module_t * module)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 
fb_close(struct hw_device_t * device)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 
fb_alloc_framebuffer_dmabuf(private_module_t * m,private_handle_t * hnd)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 
fb_alloc_from_ion_module(mali_gralloc_module * m,size_t buffer_size,uint64_t consumer_usage,uint64_t producer_usage,buffer_handle_t * pHandle)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 
fb_alloc_framebuffer_locked(mali_gralloc_module * m,uint64_t consumer_usage,uint64_t producer_usage,buffer_handle_t * pHandle,int * stride,int * byte_stride)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 
fb_alloc_framebuffer(mali_gralloc_module * m,uint64_t consumer_usage,uint64_t producer_usage,buffer_handle_t * pHandle,int * stride,int * byte_stride)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 
compositionComplete(struct framebuffer_device_t * dev)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 
framebuffer_device_open(hw_module_t const * module,const char * name,hw_device_t ** device)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