summaryrefslogtreecommitdiff
path: root/framebuffer.cpp (plain)
blob: b92e16d3d860d7ef099c49e3455dfc6778304c1b
1#include <string.h>
2#include <stdlib.h>
3#include <errno.h>
4#include <fcntl.h>
5#include <sys/ioctl.h>
6//#include <linux/ion.h>
7//#include <ion/ion.h>
8#include <linux/fb.h>
9
10//#define LOG_NDEBUG 0
11#define LOG_TAG "FrameBuffer"
12
13#include <cutils/log.h>
14#include <sys/time.h>
15#include <utils/Timers.h>
16#include <cutils/atomic.h>
17#include <cutils/properties.h>
18#include <hardware/hardware.h>
19#include <hardware/gralloc.h>
20#include "framebuffer.h"
21
22#include <hardware/hwcomposer_defs.h>
23#include <GLES/gl.h>
24
25#ifndef __gl_h_
26#error a
27#endif
28
29#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE
30#include "gralloc_vsync_report.h"
31#endif
32
33#include "gralloc_priv.h"
34#include "gralloc_helper.h"
35
36
37#ifdef DEBUG_EXTERNAL_DISPLAY_ON_PANEL
38 // 3 for panel, 3 for hdmi
39#define NUM_BUFFERS (6)
40
41#else
42
43// numbers of buffers for page flipping
44#ifndef NUM_BUFFERS
45#define NUM_BUFFERS (2)
46#endif
47
48#endif
49
50enum
51{
52 PAGE_FLIP = 0x00000001,
53};
54/*
55 framebuffer interface api to other module to use.
56*/
57
58int bits_per_pixel()
59{
60 char fb_bits[PROPERTY_VALUE_MAX];
61 int bits_per_pixel = 16;
62
63 if (property_get("sys.fb.bits", fb_bits, NULL) > 0 && atoi(fb_bits) == 32)
64 {
65 return 32;
66 }
67 return 16;
68}
69
70bool osd_afbcd_enable()
71{
72 char osd_afbcd[PROPERTY_VALUE_MAX];
73 if (property_get("osd.afbcd.enable", osd_afbcd, NULL ) > 0 && atoi(osd_afbcd) == 0)
74 {
75 return false;
76 }
77 return true;
78}
79
80#ifndef SINGLE_EXTERNAL_DISPLAY_USE_FB1
81int update_cursor_buffer_locked(struct framebuffer_info_t* cbinfo, int xres, int yres)
82{
83 char const * const device_template[] =
84 {
85 "/dev/graphics/fb%u",
86 "/dev/fb%u",
87 NULL
88 };
89
90 int i = 0;
91 char name[64];
92
93 while ((cbinfo->fd == -1) && device_template[i])
94 {
95 snprintf(name, 64, device_template[i], cbinfo->fbIdx);
96 cbinfo->fd = open(name, O_RDWR, 0);
97 i++;
98 }
99
100 ALOGE("update_cursor_buffer_locked of fb idx (%d)",cbinfo->fbIdx);
101
102 if (cbinfo->fd < 0)
103 {
104 return -errno;
105 }
106
107 struct fb_fix_screeninfo finfo;
108 if (ioctl(cbinfo->fd, FBIOGET_FSCREENINFO, &finfo) == -1)
109 {
110 return -errno;
111 }
112
113 struct fb_var_screeninfo info;
114 if (ioctl(cbinfo->fd, FBIOGET_VSCREENINFO, &info) == -1)
115 {
116 return -errno;
117 }
118
119 ALOGE("vinfo. %d %d", info.xres, info.yres);
120
121 info.xoffset = info.yoffset = 0;
122 if (bits_per_pixel() == 16)
123 {
124 /*
125 * Explicitly request 5/6/5
126 */
127 info.bits_per_pixel = 16;
128 info.red.offset = 11;
129 info.red.length = 5;
130 info.green.offset = 5;
131 info.green.length = 6;
132 info.blue.offset = 0;
133 info.blue.length = 5;
134 info.transp.offset = 0;
135 info.transp.length = 0;
136 }
137 else
138 {
139 /*
140 * Explicitly request 8/8/8/8
141 */
142 info.bits_per_pixel = 32;
143 info.red.offset = 0;
144 info.red.length = 8;
145 info.green.offset = 8;
146 info.green.length = 8;
147 info.blue.offset = 16;
148 info.blue.length = 8;
149 info.transp.offset = 24;
150 info.transp.length = 8;
151 }
152
153 info.xres_virtual = info.xres = xres;
154 info.yres_virtual = info.yres = yres;
155
156 if (ioctl(cbinfo->fd, FBIOPUT_VSCREENINFO, &info) == -1)
157 {
158 ALOGE("set vinfo fail\n");
159 }
160
161 if (ioctl(cbinfo->fd, FBIOGET_VSCREENINFO, &info) == -1)
162 {
163 ALOGE("get info fail\n");
164 return -errno;
165 }
166
167 if (int(info.width) <= 0 || int(info.height) <= 0)
168 {
169 // the driver doesn't return that information
170 // default to 160 dpi
171 info.width = ((info.xres * 25.4f)/160.0f + 0.5f);
172 info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
173 }
174
175 AINF("using (fd=%d)\n"
176 "id = %s\n"
177 "xres = %d px\n"
178 "yres = %d px\n"
179 "xres_virtual = %d px\n"
180 "yres_virtual = %d px\n"
181 "bpp = %d\n",
182 cbinfo->fd,
183 finfo.id,
184 info.xres,
185 info.yres,
186 info.xres_virtual,
187 info.yres_virtual,
188 info.bits_per_pixel);
189
190 AINF("width = %d mm \n"
191 "height = %d mm \n",
192 info.width,
193 info.height);
194
195 if (ioctl(cbinfo->fd, FBIOGET_FSCREENINFO, &finfo) == -1)
196 {
197 return -errno;
198 }
199
200 if (finfo.smem_len <= 0)
201 {
202 return -errno;
203 }
204
205 cbinfo->info = info;
206 cbinfo->finfo = finfo;
207 ALOGD("update_cursor_buffer_locked: finfo.line_length is 0x%x,info.yres_virtual is 0x%x", finfo.line_length, info.yres_virtual);
208 cbinfo->fbSize = round_up_to_page_size(finfo.line_length * info.yres_virtual);
209
210 return 0;
211}
212
213
214int init_cursor_buffer_locked(struct framebuffer_info_t* cbinfo)
215{
216 char const * const device_template[] =
217 {
218 "/dev/graphics/fb%u",
219 "/dev/fb%u",
220 NULL
221 };
222
223 int fd = -1;
224 int i = 0;
225 char name[64];
226
227 while ((fd == -1) && device_template[i])
228 {
229 snprintf(name, 64, device_template[i], cbinfo->fbIdx);
230 fd = open(name, O_RDWR, 0);
231 i++;
232 }
233
234 ALOGE("init_cursor_buffer_locked of dev:(%s),fb idx (%d)",name,cbinfo->fbIdx);
235
236 if (fd < 0)
237 {
238 return -errno;
239 }
240
241 struct fb_fix_screeninfo finfo;
242 if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
243 {
244 return -errno;
245 }
246
247 struct fb_var_screeninfo info;
248 if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
249 {
250 return -errno;
251 }
252
253 ALOGE("vinfo. %d %d", info.xres, info.yres);
254
255 info.xoffset = info.yoffset = 0;
256
257 if (bits_per_pixel() == 16)
258 {
259 /*
260 * Explicitly request 5/6/5
261 */
262 info.bits_per_pixel = 16;
263 info.red.offset = 11;
264 info.red.length = 5;
265 info.green.offset = 5;
266 info.green.length = 6;
267 info.blue.offset = 0;
268 info.blue.length = 5;
269 info.transp.offset = 0;
270 info.transp.length = 0;
271 }
272 else
273 {
274 /*
275 * Explicitly request 8/8/8/8
276 */
277 info.bits_per_pixel = 32;
278 info.red.offset = 0;
279 info.red.length = 8;
280 info.green.offset = 8;
281 info.green.length = 8;
282 info.blue.offset = 16;
283 info.blue.length = 8;
284 info.transp.offset = 24;
285 info.transp.length = 8;
286 }
287
288 if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1)
289 {
290 ALOGE("set vinfo fail\n");
291 }
292
293 if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
294 {
295 ALOGE("get info fail\n");
296 return -errno;
297 }
298
299 if (int(info.width) <= 0 || int(info.height) <= 0)
300 {
301 // the driver doesn't return that information
302 // default to 160 dpi
303 info.width = ((info.xres * 25.4f)/160.0f + 0.5f);
304 info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
305 }
306
307 //float xdpi = (info.xres * 25.4f) / info.width;
308 //float ydpi = (info.yres * 25.4f) / info.height;
309
310 AINF("using (fd=%d)\n"
311 "id = %s\n"
312 "xres = %d px\n"
313 "yres = %d px\n"
314 "xres_virtual = %d px\n"
315 "yres_virtual = %d px\n"
316 "bpp = %d\n",
317 fd,
318 finfo.id,
319 info.xres,
320 info.yres,
321 info.xres_virtual,
322 info.yres_virtual,
323 info.bits_per_pixel);
324
325 AINF("width = %d mm \n"
326 "height = %d mm \n",
327 info.width,
328 info.height);
329
330 if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
331 {
332 return -errno;
333 }
334
335 if (finfo.smem_len <= 0)
336 {
337 return -errno;
338 }
339
340 cbinfo->info = info;
341 cbinfo->finfo = finfo;
342 cbinfo->fd = fd;
343 ALOGE("init_cursor_buffer_locked: finfo.line_length is 0x%x,info.yres_virtual is 0x%x", finfo.line_length, info.yres_virtual);
344 cbinfo->fbSize = round_up_to_page_size(finfo.line_length * info.yres_virtual);
345
346 return 0;
347}
348#endif
349
350
351int init_frame_buffer_locked(struct framebuffer_info_t* fbinfo)
352{
353 char const * const device_template[] =
354 {
355 "/dev/graphics/fb%u",
356 "/dev/fb%u",
357 NULL
358 };
359
360 int fd = -1;
361 int i = 0;
362 char name[64];
363
364 while ((fd == -1) && device_template[i])
365 {
366 snprintf(name, 64, device_template[i], fbinfo->fbIdx);
367 fd = open(name, O_RDWR, 0);
368 i++;
369 }
370
371 ALOGE("init_frame_buffer_locked of dev:(%s),fb idx (%d)",name,fbinfo->fbIdx);
372
373 if (fd < 0)
374 {
375 return -errno;
376 }
377
378 struct fb_fix_screeninfo finfo;
379 if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
380 {
381 return -errno;
382 }
383
384 struct fb_var_screeninfo info;
385 if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
386 {
387 return -errno;
388 }
389
390 info.reserved[0] = 0;
391 info.reserved[1] = 0;
392 info.reserved[2] = 0;
393 info.xoffset = 0;
394 info.yoffset = 0;
395 info.activate = FB_ACTIVATE_NOW;
396
397 if (bits_per_pixel() == 16)
398 {
399 /*
400 * Explicitly request 5/6/5
401 */
402 info.bits_per_pixel = 16;
403 info.red.offset = 11;
404 info.red.length = 5;
405 info.green.offset = 5;
406 info.green.length = 6;
407 info.blue.offset = 0;
408 info.blue.length = 5;
409 info.transp.offset = 0;
410 info.transp.length = 0;
411 }
412 else
413 {
414 /*
415 * Explicitly request 8/8/8/8
416 */
417 info.bits_per_pixel = 32;
418 info.red.offset = 0;
419 info.red.length = 8;
420 info.green.offset = 8;
421 info.green.length = 8;
422 info.blue.offset = 16;
423 info.blue.length = 8;
424 info.transp.offset = 24;
425 info.transp.length = 8;
426 }
427
428 /*
429 * Request NUM_BUFFERS screens (at lest 2 for page flipping)
430 */
431 info.yres_virtual = info.yres * NUM_BUFFERS;
432
433 uint32_t flags = PAGE_FLIP;
434 if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1)
435 {
436 info.yres_virtual = info.yres;
437 flags &= ~PAGE_FLIP;
438 AWAR( "FBIOPUT_VSCREENINFO failed, page flipping not supported fd: %d", fd );
439 }
440
441 if (info.yres_virtual < info.yres * 2)
442 {
443 // we need at least 2 for page-flipping
444 info.yres_virtual = info.yres;
445 flags &= ~PAGE_FLIP;
446 AWAR( "page flipping not supported (yres_virtual=%d, requested=%d)", info.yres_virtual, info.yres*2 );
447 }
448
449 if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
450 {
451 return -errno;
452 }
453
454 int refreshRate = 0;
455 if ( info.pixclock > 0 )
456 {
457 refreshRate = 1000000000000000LLU /
458 (
459 uint64_t( info.upper_margin + info.lower_margin + info.yres + info.hsync_len )
460 * ( info.left_margin + info.right_margin + info.xres + info.vsync_len )
461 * info.pixclock
462 );
463 }
464 else
465 {
466 AWAR( "fbdev pixclock is zero for fd: %d", fd );
467 }
468
469 if (refreshRate == 0)
470 {
471 //refreshRate = 50*1000; // 50 Hz
472 refreshRate = 60*1000; // 60 Hz
473 }
474
475 if (int(info.width) <= 0 || int(info.height) <= 0)
476 {
477 // the driver doesn't return that information
478 // default to 160 dpi
479 info.width = ((info.xres * 25.4f)/160.0f + 0.5f);
480 info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
481 }
482
483 float xdpi = (info.xres * 25.4f) / info.width;
484 float ydpi = (info.yres * 25.4f) / info.height;
485 float fps = refreshRate / 1000.0f;
486
487 AINF("using (fd=%d)\n"
488 "id = %s\n"
489 "xres = %d px\n"
490 "yres = %d px\n"
491 "xres_virtual = %d px\n"
492 "yres_virtual = %d px\n"
493 "bpp = %d\n"
494 "r = %2u:%u\n"
495 "g = %2u:%u\n"
496 "b = %2u:%u\n",
497 fd,
498 finfo.id,
499 info.xres,
500 info.yres,
501 info.xres_virtual,
502 info.yres_virtual,
503 info.bits_per_pixel,
504 info.red.offset, info.red.length,
505 info.green.offset, info.green.length,
506 info.blue.offset, info.blue.length);
507
508 AINF("width = %d mm (%f dpi)\n"
509 "height = %d mm (%f dpi)\n"
510 "refresh rate = %.2f Hz\n",
511 info.width, xdpi,
512 info.height, ydpi,
513 fps);
514
515 if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
516 {
517 return -errno;
518 }
519
520 if (finfo.smem_len <= 0)
521 {
522 return -errno;
523 }
524
525 fbinfo->info = info;
526 fbinfo->finfo = finfo;
527 fbinfo->xdpi = xdpi;
528 fbinfo->ydpi = ydpi;
529 fbinfo->fps = fps;
530 fbinfo->fd = fd;
531 fbinfo->flipFlags = flags;
532 fbinfo->fbSize = round_up_to_page_size(finfo.line_length * info.yres_virtual);
533
534 return 0;
535}
536int fb_post_with_fence_locked(struct framebuffer_info_t* fbinfo,buffer_handle_t hnd,int in_fence)
537{
538#define FBIOPUT_OSD_SYNC_ADD 0x4518
539 typedef struct{
540 unsigned int xoffset;
541 unsigned int yoffset;
542 int in_fen_fd;
543 int out_fen_fd;
544 }fb_sync_request_t;
545 private_handle_t const* buffer = reinterpret_cast<private_handle_t const*>(hnd);
546
547 //wait fence sync
548 //sync_wait(in_fence, 3000);
549 //close(in_fence);
550 //in_fence = -1;
551 //set sync request
552
553 fb_sync_request_t sync_req;
554 memset(&sync_req,0,sizeof(fb_sync_request_t));
555 sync_req.xoffset=fbinfo->info.xoffset;
556 sync_req.yoffset= buffer->offset / fbinfo->finfo.line_length;
557 sync_req.in_fen_fd=in_fence;
558 //ALOGD( "req offset:%d\n",sync_req.yoffset);
559 ioctl(fbinfo->fd, FBIOPUT_OSD_SYNC_ADD, &sync_req);
560 //ALOGD( "post offset:%d\n",buffer->offset/fbinfo->finfo.line_length);
561 //TODO:: need update with kernel change.
562 //fb_post_locked(fbinfo,hnd);
563
564 int out_fence = sync_req.out_fen_fd;
565 /*nsecs_t origin=systemTime(CLOCK_MONOTONIC);
566 ALOGD( "--sync wait: %d,begin:%lld\n",out_fence,origin);
567 sync_wait(out_fence, 3000);
568 close(out_fence);
569 nsecs_t diff=systemTime(CLOCK_MONOTONIC)-origin;
570 ALOGD( "++sync wait: %d,wait_delay:%lld\n",out_fence,diff);*/
571
572 return out_fence;
573}
574
575int fb_post_locked(struct framebuffer_info_t* fbinfo, buffer_handle_t hnd)
576{
577 private_handle_t const* buffer = reinterpret_cast<private_handle_t const*>(hnd);
578 fbinfo->info.activate = FB_ACTIVATE_VBL;
579 fbinfo->info.yoffset = buffer->offset / fbinfo->finfo.line_length;
580
581 //ALOGD("fbpost on slot (%d)",fbinfo->info.yoffset/fbinfo->info.yres);
582
583#ifdef STANDARD_LINUX_SCREEN
584 int interrupt;
585#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
586#define S3CFB_SET_VSYNC_INT _IOW('F', 206, unsigned int)
587 if (ioctl(fbinfo->fd, FBIOPAN_DISPLAY, &fbinfo->info) == -1)
588 {
589 AERR( "FBIOPAN_DISPLAY failed for fd: %d", fbinfo->fd );
590 return 0;
591 }
592#if PLATFORM_SDK_VERSION >= 16
593 if (swapInterval == 1 && !(buffer->usage & GRALLOC_USAGE_HW_COMPOSER))
594#else
595 if (swapInterval == 1)
596#endif
597 {
598 // enable VSYNC
599 interrupt = 1;
600 if (ioctl(fbinfo->fd, S3CFB_SET_VSYNC_INT, &interrupt) < 0)
601 {
602 AERR( "S3CFB_SET_VSYNC_INT enable failed for fd: %d", fbinfo->fd );
603 return 0;
604 }
605 // wait for VSYNC
606#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE
607 gralloc_mali_vsync_report(MALI_VSYNC_EVENT_BEGIN_WAIT);
608#endif
609 int crtc = 0;
610 if (ioctl(fbinfo->fd, FBIO_WAITFORVSYNC, &crtc) < 0)
611 {
612 AERR( "FBIO_WAITFORVSYNC failed for fd: %d", fbinfo->fd );
613#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE
614 gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT);
615#endif
616 return 0;
617 }
618#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE
619 gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT);
620#endif
621 // disable VSYNC
622 interrupt = 0;
623 if (ioctl(fbinfo->fd, S3CFB_SET_VSYNC_INT, &interrupt) < 0)
624 {
625 AERR( "S3CFB_SET_VSYNC_INT disable failed for fd: %d", fbinfo->fd );
626 return 0;
627 }
628 }
629#else
630 /*Standard Android way*/
631#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE
632 gralloc_mali_vsync_report(MALI_VSYNC_EVENT_BEGIN_WAIT);
633#endif
634 ALOGD("current yoffset %d\n",fbinfo->info.yoffset);
635 //if (ioctl(fbinfo->fd, FBIOPUT_VSCREENINFO, &fbinfo->info) == -1)
636 if (ioctl(fbinfo->fd, FBIOPAN_DISPLAY, &fbinfo->info) == -1)
637 {
638 AERR( "FBIOPUT_VSCREENINFO failed for fd: %d", fbinfo->fd );
639#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE
640 gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT);
641#endif
642 return -errno;
643 }
644#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE
645 gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT);
646#endif
647#endif
648
649 fbinfo->currentBuffer = buffer;
650
651 return 0;
652}
653
654int getOsdIdx(int display_type)
655{
656#ifdef DEBUG_EXTERNAL_DISPLAY_ON_PANEL
657 return 0;
658#else
659 if (display_type == HWC_DISPLAY_PRIMARY)
660 return 0;
661 if (display_type == HWC_DISPLAY_EXTERNAL)
662 {
663#ifndef SINGLE_EXTERNAL_DISPLAY_USE_FB1
664 return 2;
665#else
666 return 1;
667#endif
668 }
669#endif
670 return -1;
671}
672
673
674unsigned int get_num_fb_buffers() {
675 ALOGD("****************************** %d\n",NUM_BUFFERS);
676 return NUM_BUFFERS;
677}
678
679