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