blob: bacefeedcc085a772d9458f7d31c656f0ec1a5b7 [file] [log] [blame]
Vishal Bhoj78e90492015-12-07 01:36:32 +05301/*
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
43static int swapInterval = 1;
44
45enum
46{
47 PAGE_FLIP = 0x00000001,
48};
49
50
51static 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
67static 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
Chia-I Wu57b9e8a2017-05-08 12:50:36 -070097 int fbdev_fd = m->framebuffer->shallow_fbdev_fd;
98
99 if (ioctl(fbdev_fd, FBIOPAN_DISPLAY, &m->info) == -1)
Vishal Bhoj78e90492015-12-07 01:36:32 +0530100 {
Chia-I Wu57b9e8a2017-05-08 12:50:36 -0700101 AERR("FBIOPAN_DISPLAY failed for fd: %d", fbdev_fd);
Vishal Bhoj78e90492015-12-07 01:36:32 +0530102 m->base.unlock(&m->base, buffer);
103 return 0;
104 }
105
106 if (swapInterval == 1)
107 {
108 // enable VSYNC
109 interrupt = 1;
110
Chia-I Wu57b9e8a2017-05-08 12:50:36 -0700111 if (ioctl(fbdev_fd, S3CFB_SET_VSYNC_INT, &interrupt) < 0)
Vishal Bhoj78e90492015-12-07 01:36:32 +0530112 {
Chia-I Wu57b9e8a2017-05-08 12:50:36 -0700113 // AERR("S3CFB_SET_VSYNC_INT enable failed for fd: %d", fbdev_fd);
Vishal Bhoj78e90492015-12-07 01:36:32 +0530114 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
Chia-I Wu57b9e8a2017-05-08 12:50:36 -0700123 if (ioctl(fbdev_fd, FBIO_WAITFORVSYNC, &crtc) < 0)
Vishal Bhoj78e90492015-12-07 01:36:32 +0530124 {
Chia-I Wu57b9e8a2017-05-08 12:50:36 -0700125 AERR("FBIO_WAITFORVSYNC failed for fd: %d", fbdev_fd);
Vishal Bhoj78e90492015-12-07 01:36:32 +0530126#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
Chia-I Wu57b9e8a2017-05-08 12:50:36 -0700138 if (ioctl(fbdev_fd, S3CFB_SET_VSYNC_INT, &interrupt) < 0)
Vishal Bhoj78e90492015-12-07 01:36:32 +0530139 {
Chia-I Wu57b9e8a2017-05-08 12:50:36 -0700140 AERR("S3CFB_SET_VSYNC_INT disable failed for fd: %d", fbdev_fd);
Vishal Bhoj78e90492015-12-07 01:36:32 +0530141 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
Chia-I Wu57b9e8a2017-05-08 12:50:36 -0700151 if (ioctl(fbdev_fd, FBIOPUT_VSCREENINFO, &m->info) == -1)
Vishal Bhoj78e90492015-12-07 01:36:32 +0530152 {
Chia-I Wu57b9e8a2017-05-08 12:50:36 -0700153 AERR("FBIOPUT_VSCREENINFO failed for fd: %d", fbdev_fd);
Vishal Bhoj78e90492015-12-07 01:36:32 +0530154#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
188int 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,
Chia-I Wu57b9e8a2017-05-08 12:50:36 -0700388 0, fd, 0);
Vishal Bhoj78e90492015-12-07 01:36:32 +0530389
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
408static 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
416static 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
John Stultz37287452016-01-20 20:08:46 -0800425 free(dev);
Vishal Bhoj78e90492015-12-07 01:36:32 +0530426 }
427
428 return 0;
429}
430
431int 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
451int 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 */
John Stultz37287452016-01-20 20:08:46 -0800473 framebuffer_device_t *dev = (framebuffer_device_t *)malloc(sizeof(framebuffer_device_t));
Jinguang Dong58c515b2017-05-02 10:20:19 +0800474 if (dev == NULL)
475 {
476 AERR("Error to malloc the framebuffer (%s)", strerror(errno));
477 gralloc_close(gralloc_device);
478 return -ENOMEM;
479 }
Vishal Bhoj78e90492015-12-07 01:36:32 +0530480 memset(dev, 0, sizeof(*dev));
481
482 /* initialize the procs */
483 dev->common.tag = HARDWARE_DEVICE_TAG;
484 dev->common.version = 0;
485 dev->common.module = const_cast<hw_module_t *>(module);
486 dev->common.close = fb_close;
487 dev->setSwapInterval = fb_set_swap_interval;
488 dev->post = fb_post;
489 dev->setUpdateRect = 0;
490 dev->compositionComplete = &compositionComplete;
491
492 int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3);
493 const_cast<uint32_t &>(dev->flags) = 0;
494 const_cast<uint32_t &>(dev->width) = m->info.xres;
495 const_cast<uint32_t &>(dev->height) = m->info.yres;
496 const_cast<int &>(dev->stride) = stride;
497#ifdef GRALLOC_16_BITS
498 const_cast<int &>(dev->format) = HAL_PIXEL_FORMAT_RGB_565;
499#else
500 const_cast<int &>(dev->format) = HAL_PIXEL_FORMAT_RGBA_8888;
501#endif
502 const_cast<float &>(dev->xdpi) = m->xdpi;
503 const_cast<float &>(dev->ydpi) = m->ydpi;
504 const_cast<float &>(dev->fps) = m->fps;
505 const_cast<int &>(dev->minSwapInterval) = 0;
506 const_cast<int &>(dev->maxSwapInterval) = 1;
507 *device = &dev->common;
508 status = 0;
509
510 MALI_IGNORE(name);
511 return status;
512}