• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 		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     = 0;
256 	info.red.length     = 8;
257 	info.green.offset   = 8;
258 	info.green.length   = 8;
259 	info.blue.offset    = 16;
260 	info.blue.length    = 8;
261 	info.transp.offset  = 24;
262 	info.transp.length  = 8;
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, dup(fd), 0);
387 
388 	module->numBuffers = info.yres_virtual / info.yres;
389 	module->bufferMask = 0;
390 
391 #if GRALLOC_ARM_UMP_MODULE
392 #ifdef IOCTL_GET_FB_UMP_SECURE_ID
393 	ioctl(fd, IOCTL_GET_FB_UMP_SECURE_ID, &module->framebuffer->ump_id);
394 #endif
395 
396 	if ((int)UMP_INVALID_SECURE_ID != module->framebuffer->ump_id)
397 	{
398 		AINF("framebuffer accessed with UMP secure ID %i\n", module->framebuffer->ump_id);
399 	}
400 
401 #endif
402 
403 	return 0;
404 }
405 
init_frame_buffer(struct private_module_t * module)406 static int init_frame_buffer(struct private_module_t *module)
407 {
408 	pthread_mutex_lock(&module->lock);
409 	int err = init_frame_buffer_locked(module);
410 	pthread_mutex_unlock(&module->lock);
411 	return err;
412 }
413 
fb_close(struct hw_device_t * device)414 static int fb_close(struct hw_device_t *device)
415 {
416 	framebuffer_device_t *dev = reinterpret_cast<framebuffer_device_t *>(device);
417 
418 	if (dev)
419 	{
420 #if GRALLOC_ARM_UMP_MODULE
421 		ump_close();
422 #endif
423 		free(dev);
424 	}
425 
426 	return 0;
427 }
428 
compositionComplete(struct framebuffer_device_t * dev)429 int compositionComplete(struct framebuffer_device_t *dev)
430 {
431 	MALI_IGNORE(dev);
432 	/* By doing a finish here we force the GL driver to start rendering
433 	   all the drawcalls up to this point, and to wait for the rendering to be complete.*/
434 	glFinish();
435 	/* The rendering of the backbuffer is now completed.
436 	   When SurfaceFlinger later does a call to eglSwapBuffer(), the swap will be done
437 	   synchronously in the same thread, and not asynchronoulsy in a background thread later.
438 	   The SurfaceFlinger requires this behaviour since it releases the lock on all the
439 	   SourceBuffers (Layers) after the compositionComplete() function returns.
440 	   However this "bad" behaviour by SurfaceFlinger should not affect performance,
441 	   since the Applications that render the SourceBuffers (Layers) still get the
442 	   full renderpipeline using asynchronous rendering. So they perform at maximum speed,
443 	   and because of their complexity compared to the Surface flinger jobs, the Surface flinger
444 	   is normally faster even if it does everyhing synchronous and serial.
445 	   */
446 	return 0;
447 }
448 
framebuffer_device_open(hw_module_t const * module,const char * name,hw_device_t ** device)449 int framebuffer_device_open(hw_module_t const *module, const char *name, hw_device_t **device)
450 {
451 	int status = -EINVAL;
452 
453 	alloc_device_t *gralloc_device;
454 	status = gralloc_open(module, &gralloc_device);
455 
456 	if (status < 0)
457 	{
458 		return status;
459 	}
460 
461 	private_module_t *m = (private_module_t *)module;
462 	status = init_frame_buffer(m);
463 
464 	if (status < 0)
465 	{
466 		gralloc_close(gralloc_device);
467 		return status;
468 	}
469 
470 	/* initialize our state here */
471 	framebuffer_device_t *dev = (framebuffer_device_t *)malloc(sizeof(framebuffer_device_t));
472 	memset(dev, 0, sizeof(*dev));
473 
474 	/* initialize the procs */
475 	dev->common.tag = HARDWARE_DEVICE_TAG;
476 	dev->common.version = 0;
477 	dev->common.module = const_cast<hw_module_t *>(module);
478 	dev->common.close = fb_close;
479 	dev->setSwapInterval = fb_set_swap_interval;
480 	dev->post = fb_post;
481 	dev->setUpdateRect = 0;
482 	dev->compositionComplete = &compositionComplete;
483 
484 	int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3);
485 	const_cast<uint32_t &>(dev->flags) = 0;
486 	const_cast<uint32_t &>(dev->width) = m->info.xres;
487 	const_cast<uint32_t &>(dev->height) = m->info.yres;
488 	const_cast<int &>(dev->stride) = stride;
489 #ifdef GRALLOC_16_BITS
490 	const_cast<int &>(dev->format) = HAL_PIXEL_FORMAT_RGB_565;
491 #else
492 	const_cast<int &>(dev->format) = HAL_PIXEL_FORMAT_RGBA_8888;
493 #endif
494 	const_cast<float &>(dev->xdpi) = m->xdpi;
495 	const_cast<float &>(dev->ydpi) = m->ydpi;
496 	const_cast<float &>(dev->fps) = m->fps;
497 	const_cast<int &>(dev->minSwapInterval) = 0;
498 	const_cast<int &>(dev->maxSwapInterval) = 1;
499 	*device = &dev->common;
500 	status = 0;
501 
502 	MALI_IGNORE(name);
503 	return status;
504 }
505