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 
fb_set_swap_interval(struct framebuffer_device_t * dev,int interval)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 
fb_post(struct framebuffer_device_t * dev,buffer_handle_t buffer)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 
init_frame_buffer_locked(struct private_module_t * module)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 
init_frame_buffer(struct private_module_t * module)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 
fb_close(struct hw_device_t * device)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 
compositionComplete(struct framebuffer_device_t * dev)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 
framebuffer_device_open(hw_module_t const * module,const char * name,hw_device_t ** device)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 	memset(dev, 0, sizeof(*dev));
475 
476 	/* initialize the procs */
477 	dev->common.tag = HARDWARE_DEVICE_TAG;
478 	dev->common.version = 0;
479 	dev->common.module = const_cast<hw_module_t *>(module);
480 	dev->common.close = fb_close;
481 	dev->setSwapInterval = fb_set_swap_interval;
482 	dev->post = fb_post;
483 	dev->setUpdateRect = 0;
484 	dev->compositionComplete = &compositionComplete;
485 
486 	int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3);
487 	const_cast<uint32_t &>(dev->flags) = 0;
488 	const_cast<uint32_t &>(dev->width) = m->info.xres;
489 	const_cast<uint32_t &>(dev->height) = m->info.yres;
490 	const_cast<int &>(dev->stride) = stride;
491 #ifdef GRALLOC_16_BITS
492 	const_cast<int &>(dev->format) = HAL_PIXEL_FORMAT_RGB_565;
493 #else
494 	const_cast<int &>(dev->format) = HAL_PIXEL_FORMAT_RGBA_8888;
495 #endif
496 	const_cast<float &>(dev->xdpi) = m->xdpi;
497 	const_cast<float &>(dev->ydpi) = m->ydpi;
498 	const_cast<float &>(dev->fps) = m->fps;
499 	const_cast<int &>(dev->minSwapInterval) = 0;
500 	const_cast<int &>(dev->maxSwapInterval) = 1;
501 	*device = &dev->common;
502 	status = 0;
503 
504 	MALI_IGNORE(name);
505 	return status;
506 }
507