blob: fa60eb5b252769ebc95617adf558d2709c542136 [file] [log] [blame]
John Stultz16100f62017-05-03 11:12:18 -07001/*
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 <stdlib.h>
23#include <sys/ioctl.h>
24#include <linux/fb.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#include "alloc_device.h"
34#include "gralloc_priv.h"
35#include "gralloc_helper.h"
36#include "gralloc_vsync.h"
37
38#define STANDARD_LINUX_SCREEN
39
40// numbers of buffers for page flipping
41#define NUM_BUFFERS NUM_FB_BUFFERS
42
43enum
44{
45 PAGE_FLIP = 0x00000001,
46};
47
48
49static int fb_set_swap_interval(struct framebuffer_device_t* dev, int interval)
50{
51 if (interval < dev->minSwapInterval)
52 {
53 interval = dev->minSwapInterval;
54 }
55 else if (interval > dev->maxSwapInterval)
56 {
57 interval = dev->maxSwapInterval;
58 }
59
60 private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module);
61 m->swapInterval = interval;
62
63 if (0 == interval) gralloc_vsync_disable(dev);
64 else gralloc_vsync_enable(dev);
65
66 return 0;
67}
68
69static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
70{
71 if (private_handle_t::validate(buffer) < 0)
72 {
73 return -EINVAL;
74 }
75
76 private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(buffer);
77 private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module);
78
79 if (m->currentBuffer)
80 {
81 m->base.unlock(&m->base, m->currentBuffer);
82 m->currentBuffer = 0;
83 }
84
85 if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)
86 {
87 m->base.lock(&m->base, buffer, private_module_t::PRIV_USAGE_LOCKED_FOR_POST,
88 0, 0, m->info.xres, m->info.yres, NULL);
89
90 const size_t offset = (uintptr_t)hnd->base - (uintptr_t)m->framebuffer->base;
91 int interrupt;
92 m->info.activate = FB_ACTIVATE_VBL;
93 m->info.yoffset = offset / m->finfo.line_length;
94
Chia-I Wu5f82a372017-05-08 12:50:36 -070095 int fbdev_fd = m->framebuffer->shallow_fbdev_fd;
John Stultz16100f62017-05-03 11:12:18 -070096#ifdef STANDARD_LINUX_SCREEN
Chia-I Wu5f82a372017-05-08 12:50:36 -070097 if (ioctl(fbdev_fd, FBIOPAN_DISPLAY, &m->info) == -1)
John Stultz16100f62017-05-03 11:12:18 -070098 {
Chia-I Wu5f82a372017-05-08 12:50:36 -070099 AERR( "FBIOPAN_DISPLAY failed for fd: %d", fbdev_fd );
John Stultz16100f62017-05-03 11:12:18 -0700100 m->base.unlock(&m->base, buffer);
101 return -errno;
102 }
103#else /*Standard Android way*/
Chia-I Wu5f82a372017-05-08 12:50:36 -0700104 if (ioctl(fbdev_fd, FBIOPUT_VSCREENINFO, &m->info) == -1)
John Stultz16100f62017-05-03 11:12:18 -0700105 {
Chia-I Wu5f82a372017-05-08 12:50:36 -0700106 AERR( "FBIOPUT_VSCREENINFO failed for fd: %d", fbdev_fd );
John Stultz16100f62017-05-03 11:12:18 -0700107 m->base.unlock(&m->base, buffer);
108 return -errno;
109 }
110#endif
111 if ( 0 != gralloc_wait_for_vsync(dev) )
112 {
Chia-I Wu5f82a372017-05-08 12:50:36 -0700113 AERR( "Gralloc wait for vsync failed for fd: %d", fbdev_fd );
John Stultz16100f62017-05-03 11:12:18 -0700114 m->base.unlock(&m->base, buffer);
115 return -errno;
116 }
117 m->currentBuffer = buffer;
118 }
119 else
120 {
121 void* fb_vaddr;
122 void* buffer_vaddr;
123
124 m->base.lock(&m->base, m->framebuffer, GRALLOC_USAGE_SW_WRITE_RARELY,
125 0, 0, m->info.xres, m->info.yres, &fb_vaddr);
126
127 m->base.lock(&m->base, buffer, GRALLOC_USAGE_SW_READ_RARELY,
128 0, 0, m->info.xres, m->info.yres, &buffer_vaddr);
129
130 // If buffer's alignment match framebuffer alignment we can do a direct copy.
131 // If not we must fallback to do an aligned copy of each line.
132 if ( hnd->byte_stride == (int)m->finfo.line_length )
133 {
134 memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres);
135 }
136 else
137 {
138 uintptr_t fb_offset = 0;
139 uintptr_t buffer_offset = 0;
140 unsigned int i;
141
142 for (i = 0; i < m->info.yres; i++)
143 {
144 memcpy((void *)((uintptr_t)fb_vaddr + fb_offset),
145 (void *)((uintptr_t)buffer_vaddr + buffer_offset),
146 m->finfo.line_length);
147
148 fb_offset += m->finfo.line_length;
149 buffer_offset += hnd->byte_stride;
150 }
151 }
152 m->base.unlock(&m->base, buffer);
153 m->base.unlock(&m->base, m->framebuffer);
154 }
155
156 return 0;
157}
158
159int init_frame_buffer_locked(struct private_module_t* module)
160{
161 if (module->framebuffer)
162 {
163 return 0; // Nothing to do, already initialized
164 }
165
166 char const * const device_template[] =
167 {
168 "/dev/graphics/fb%u",
169 "/dev/fb%u",
170 NULL
171 };
172
173 int fd = -1;
174 int i = 0;
175 char name[64];
176
177 while ((fd == -1) && device_template[i])
178 {
179 snprintf(name, 64, device_template[i], 0);
180 fd = open(name, O_RDWR, 0);
181 i++;
182 }
183
184 if (fd < 0)
185 {
186 return -errno;
187 }
188
189 struct fb_fix_screeninfo finfo;
190 if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
191 {
192 return -errno;
193 }
194
195 struct fb_var_screeninfo info;
196 if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
197 {
198 return -errno;
199 }
200
201 info.reserved[0] = 0;
202 info.reserved[1] = 0;
203 info.reserved[2] = 0;
204 info.xoffset = 0;
205 info.yoffset = 0;
206 info.activate = FB_ACTIVATE_NOW;
207
208#ifdef GRALLOC_16_BITS
209 /*
210 * Explicitly request 5/6/5
211 */
212 info.bits_per_pixel = 16;
213 info.red.offset = 11;
214 info.red.length = 5;
215 info.green.offset = 5;
216 info.green.length = 6;
217 info.blue.offset = 0;
218 info.blue.length = 5;
219 info.transp.offset = 0;
220 info.transp.length = 0;
221#else
222 /*
223 * Explicitly request 8/8/8
224 */
225 info.bits_per_pixel = 32;
226 info.red.offset = 16;
227 info.red.length = 8;
228 info.green.offset = 8;
229 info.green.length = 8;
230 info.blue.offset = 0;
231 info.blue.length = 8;
232 info.transp.offset = 0;
233 info.transp.length = 0;
234#endif
235
236 /*
237 * Request NUM_BUFFERS screens (at lest 2 for page flipping)
238 */
239 info.yres_virtual = info.yres * NUM_BUFFERS;
240
241 uint32_t flags = PAGE_FLIP;
242 if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1)
243 {
244 info.yres_virtual = info.yres;
245 flags &= ~PAGE_FLIP;
246 AWAR( "FBIOPUT_VSCREENINFO failed, page flipping not supported fd: %d", fd );
247 }
248
249 if (info.yres_virtual < info.yres * 2)
250 {
251 // we need at least 2 for page-flipping
252 info.yres_virtual = info.yres;
253 flags &= ~PAGE_FLIP;
254 AWAR( "page flipping not supported (yres_virtual=%d, requested=%d)", info.yres_virtual, info.yres*2 );
255 }
256
257 if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
258 {
259 return -errno;
260 }
261
262 int refreshRate = 0;
263 if ( info.pixclock > 0 )
264 {
265 refreshRate = 1000000000000000LLU /
266 (
267 uint64_t( info.upper_margin + info.lower_margin + info.yres + info.hsync_len )
268 * ( info.left_margin + info.right_margin + info.xres + info.vsync_len )
269 * info.pixclock
270 );
271 }
272 else
273 {
274 AWAR( "fbdev pixclock is zero for fd: %d", fd );
275 }
276
277 if (refreshRate == 0)
278 {
279 refreshRate = 60*1000; // 60 Hz
280 }
281
282 if (int(info.width) <= 0 || int(info.height) <= 0)
283 {
284 // the driver doesn't return that information
285 // default to 160 dpi
286 info.width = ((info.xres * 25.4f)/160.0f + 0.5f);
287 info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
288 }
289
290 float xdpi = (info.xres * 25.4f) / info.width;
291 float ydpi = (info.yres * 25.4f) / info.height;
292 float fps = refreshRate / 1000.0f;
293
294 AINF("using (fd=%d)\n"
295 "id = %s\n"
296 "xres = %d px\n"
297 "yres = %d px\n"
298 "xres_virtual = %d px\n"
299 "yres_virtual = %d px\n"
300 "bpp = %d\n"
301 "r = %2u:%u\n"
302 "g = %2u:%u\n"
303 "b = %2u:%u\n",
304 fd,
305 finfo.id,
306 info.xres,
307 info.yres,
308 info.xres_virtual,
309 info.yres_virtual,
310 info.bits_per_pixel,
311 info.red.offset, info.red.length,
312 info.green.offset, info.green.length,
313 info.blue.offset, info.blue.length);
314
315 AINF("width = %d mm (%f dpi)\n"
316 "height = %d mm (%f dpi)\n"
317 "refresh rate = %.2f Hz\n",
318 info.width, xdpi,
319 info.height, ydpi,
320 fps);
321
322 if (0 == strncmp(finfo.id, "CLCD FB", 7))
323 {
324 module->dpy_type = MALI_DPY_TYPE_CLCD;
325 }
326 else if (0 == strncmp(finfo.id, "ARM Mali HDLCD", 14))
327 {
328 module->dpy_type = MALI_DPY_TYPE_HDLCD;
329 }
330 else
331 {
332 module->dpy_type = MALI_DPY_TYPE_UNKNOWN;
333 }
334
335 if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
336 {
337 return -errno;
338 }
339
340 if (finfo.smem_len <= 0)
341 {
342 return -errno;
343 }
344
345 module->flags = flags;
346 module->info = info;
347 module->finfo = finfo;
348 module->xdpi = xdpi;
349 module->ydpi = ydpi;
350 module->fps = fps;
351 module->swapInterval = 1;
352
353 /*
354 * map the framebuffer
355 */
356 size_t fbSize = round_up_to_page_size(finfo.line_length * info.yres_virtual);
357 void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
358 if (vaddr == MAP_FAILED)
359 {
360 AERR( "Error mapping the framebuffer (%s)", strerror(errno) );
361 return -errno;
362 }
363
364 memset(vaddr, 0, fbSize);
365
366
367 // Create a "fake" buffer object for the entire frame buffer memory, and store it in the module
368 module->framebuffer = new private_handle_t(private_handle_t::PRIV_FLAGS_FRAMEBUFFER, GRALLOC_USAGE_HW_FB, fbSize, vaddr,
Chia-I Wu5f82a372017-05-08 12:50:36 -0700369 0, fd, 0);
John Stultz16100f62017-05-03 11:12:18 -0700370
371 module->numBuffers = info.yres_virtual / info.yres;
372 module->bufferMask = 0;
373
374 return 0;
375}
376
377static int init_frame_buffer(struct private_module_t* module)
378{
379 pthread_mutex_lock(&module->lock);
380 int err = init_frame_buffer_locked(module);
381 pthread_mutex_unlock(&module->lock);
382 return err;
383}
384
385static int fb_close(struct hw_device_t *device)
386{
387 framebuffer_device_t* dev = reinterpret_cast<framebuffer_device_t*>(device);
388 if (dev)
389 {
390 free(dev);
391 }
392 return 0;
393}
394
395int compositionComplete(struct framebuffer_device_t* dev)
396{
397 GRALLOC_UNUSED(dev);
398
399 /* By doing a finish here we force the GL driver to start rendering
400 all the drawcalls up to this point, and to wait for the rendering to be complete.*/
401 glFinish();
402 /* The rendering of the backbuffer is now completed.
403 When SurfaceFlinger later does a call to eglSwapBuffer(), the swap will be done
404 synchronously in the same thread, and not asynchronoulsy in a background thread later.
405 The SurfaceFlinger requires this behaviour since it releases the lock on all the
406 SourceBuffers (Layers) after the compositionComplete() function returns.
407 However this "bad" behaviour by SurfaceFlinger should not affect performance,
408 since the Applications that render the SourceBuffers (Layers) still get the
409 full renderpipeline using asynchronous rendering. So they perform at maximum speed,
410 and because of their complexity compared to the Surface flinger jobs, the Surface flinger
411 is normally faster even if it does everyhing synchronous and serial.
412 */
413 return 0;
414}
415
416int framebuffer_device_open(hw_module_t const* module, const char* name, hw_device_t** device)
417{
418 int status = -EINVAL;
419
420 GRALLOC_UNUSED(name);
421
422 alloc_device_t* gralloc_device;
423#if DISABLE_FRAMEBUFFER_HAL == 1
424 AERR("Framebuffer HAL not support/disabled %s",
425#ifdef MALI_DISPLAY_VERSION
426 "with MALI display enable");
427#else
428 "");
429#endif
430 return -ENODEV;
431#endif
432 status = gralloc_open(module, &gralloc_device);
433 if (status < 0)
434 {
435 return status;
436 }
437
438 private_module_t* m = (private_module_t*)module;
439 status = init_frame_buffer(m);
440
441 /* malloc is used instead of 'new' to instantiate the struct framebuffer_device_t
442 * C++11 spec specifies that if a class/struct has a const member,default constructor
443 * is deleted. So, if 'new' is used to instantiate the class/struct, it will throw
444 * error complaining about deleted constructor. Even if the struct is wrapped in a class
445 * it will still try to use the base class constructor to initialize the members, resulting
446 * in error 'deleted constructor'.
447 * This leaves two options
448 * Option 1: initialize the const members at the instantiation time. With {value1, value2 ..}
449 * Which relies on the order of the members, and if members are reordered or a new member is introduced
450 * it will end up assiging wrong value to members. Designated assignment as well has been removed in C++11
451 * Option 2: use malloc instead of 'new' to allocate the class/struct and initialize the members in code.
452 * This is the only maintainable option available.
453 */
454
455 framebuffer_device_t *dev = reinterpret_cast<framebuffer_device_t*> (malloc(sizeof(framebuffer_device_t)));
456
457 /* if either or both of init_frame_buffer() and malloc failed */
458 if ((status < 0) || (!dev))
459 {
460 gralloc_close(gralloc_device);
461 (!dev)? (void)(status = -ENOMEM) : free(dev);
462 return status;
463 }
464
465 memset(dev, 0, sizeof(*dev));
466
467 /* initialize the procs */
468 dev->common.tag = HARDWARE_DEVICE_TAG;
469 dev->common.version = 0;
470 dev->common.module = const_cast<hw_module_t*>(module);
471 dev->common.close = fb_close;
472 dev->setSwapInterval = fb_set_swap_interval;
473 dev->post = fb_post;
474 dev->setUpdateRect = 0;
475 dev->compositionComplete = &compositionComplete;
476
477 int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3);
478 const_cast<uint32_t&>(dev->flags) = 0;
479 const_cast<uint32_t&>(dev->width) = m->info.xres;
480 const_cast<uint32_t&>(dev->height) = m->info.yres;
481 const_cast<int&>(dev->stride) = stride;
482#ifdef GRALLOC_16_BITS
483 const_cast<int&>(dev->format) = HAL_PIXEL_FORMAT_RGB_565;
484#else
485 const_cast<int&>(dev->format) = HAL_PIXEL_FORMAT_BGRA_8888;
486#endif
487 const_cast<float&>(dev->xdpi) = m->xdpi;
488 const_cast<float&>(dev->ydpi) = m->ydpi;
489 const_cast<float&>(dev->fps) = m->fps;
490 const_cast<int&>(dev->minSwapInterval) = 0;
491 const_cast<int&>(dev->maxSwapInterval) = 1;
492 *device = &dev->common;
493
494 gralloc_vsync_enable(dev);
495
496 return status;
497}