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