blob: cfc480fa16d786749872086fe5f3a53b0355524e [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
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
186int 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
406static 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
414static 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
John Stultz37287452016-01-20 20:08:46 -0800423 free(dev);
Vishal Bhoj78e90492015-12-07 01:36:32 +0530424 }
425
426 return 0;
427}
428
429int 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
449int 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 */
John Stultz37287452016-01-20 20:08:46 -0800471 framebuffer_device_t *dev = (framebuffer_device_t *)malloc(sizeof(framebuffer_device_t));
Vishal Bhoj78e90492015-12-07 01:36:32 +0530472 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}