Advertisement
Guest User

Untitled

a guest
Oct 17th, 2017
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.47 KB | None | 0 0
  1. /*
  2.  * Copyright (C) 2014 The Android Open Source Project
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  *
  8.  *      http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */
  16.  
  17. #include <stdbool.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <unistd.h>
  21.  
  22. #include <fcntl.h>
  23. #include <stdio.h>
  24.  
  25. #include <sys/cdefs.h>
  26. #include <sys/ioctl.h>
  27. #include <sys/mman.h>
  28. #include <sys/types.h>
  29.  
  30. #include <linux/fb.h>
  31. #include <linux/kd.h>
  32.  
  33. #include "minui.h"
  34. #include "graphics.h"
  35. #include <pixelflinger/pixelflinger.h>
  36.  
  37. static GRSurface* fbdev_init(minui_backend*);
  38. static GRSurface* fbdev_flip(minui_backend*);
  39. static void fbdev_blank(minui_backend*, bool);
  40. static void fbdev_exit(minui_backend*);
  41.  
  42. static GRSurface gr_framebuffer[2];
  43. static bool double_buffered;
  44. static GRSurface* gr_draw = NULL;
  45. static int displayed_buffer;
  46.  
  47. static fb_var_screeninfo vi;
  48. static int fb_fd = -1;
  49. static __u32 smem_len;
  50.  
  51. static minui_backend my_backend = {
  52.     .init = fbdev_init,
  53.     .flip = fbdev_flip,
  54.     .blank = fbdev_blank,
  55.     .exit = fbdev_exit,
  56. };
  57.  
  58. minui_backend* open_fbdev() {
  59.     return &my_backend;
  60. }
  61.  
  62. static void fbdev_blank(minui_backend* backend __unused, bool blank)
  63. {
  64. #if defined(TW_NO_SCREEN_BLANK) && defined(TW_BRIGHTNESS_PATH) && defined(TW_MAX_BRIGHTNESS)
  65.     int fd;
  66.     char brightness[4];
  67.     snprintf(brightness, 4, "%03d", TW_MAX_BRIGHTNESS/2);
  68.  
  69.     fd = open(TW_BRIGHTNESS_PATH, O_RDWR);
  70.     if (fd < 0) {
  71.         perror("cannot open LCD backlight");
  72.         return;
  73.     }
  74.     write(fd, blank ? "000" : brightness, 3);
  75.     close(fd);
  76.  
  77. #ifdef TW_SECONDARY_BRIGHTNESS_PATH
  78.     fd = open(TW_SECONDARY_BRIGHTNESS_PATH, O_RDWR);
  79.     if (fd < 0) {
  80.         perror("cannot open LCD backlight 2");
  81.         return;
  82.     }
  83.     write(fd, blank ? "000" : brightness, 3);
  84.     close(fd);
  85. #endif
  86. #else
  87. #ifndef TW_NO_SCREEN_BLANK
  88.     int ret;
  89.  
  90.     ret = ioctl(fb_fd, FBIOBLANK, blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK);
  91.     if (ret < 0)
  92.         perror("ioctl(): blank");
  93. #endif
  94. #endif
  95. }
  96.  
  97. static void set_displayed_framebuffer(unsigned n)
  98. {
  99.     if (n > 1 || !double_buffered) return;
  100.  
  101.     vi.yres_virtual = gr_framebuffer[0].height * 2;
  102.     vi.yoffset = n * gr_framebuffer[0].height;
  103.     vi.bits_per_pixel = gr_framebuffer[0].pixel_bytes * 8;
  104.     if (ioctl(fb_fd, FBIOPAN_DISPLAY, &vi) < 0) {           //Test to q531
  105.         perror("pan failed");
  106.     }
  107. }
  108.    
  109. /*     if (ioctl(fb_fd, FBIOPUT_VSCREENINFO, &vi) < 0) {
  110.         perror("active fb swap failed");
  111. #ifdef TW_FBIOPAN
  112.     } else {
  113.         if (ioctl(fb_fd, FBIOPAN_DISPLAY, &vi) < 0) {
  114.             perror("pan failed");
  115.         }
  116. #endif
  117.     }
  118.     displayed_buffer = n;
  119. } */
  120.  
  121. static GRSurface* fbdev_init(minui_backend* backend) {
  122.     int retry = 20;
  123.     int fd = -1;
  124.     while (fd == -1) {
  125.         fd = open("/dev/graphics/fb0", O_RDWR);
  126.         if (fd == -1) {
  127.             if (--retry) {
  128.                 // wait for init to create the device node
  129.                 perror("cannot open fb0 (retrying)");
  130.                 usleep(100000);
  131.             } else {
  132.                 perror("cannot open fb0 (giving up)");
  133.                 return NULL;
  134.             }
  135.         }
  136.     }
  137.  
  138.     if (ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) {
  139.         perror("failed to get fb0 info (FBIOGET_VSCREENINFO)");
  140.         close(fd);
  141.         return NULL;
  142.     }
  143.  
  144. #ifdef RECOVERY_FORCE_RGB_565
  145.     // Changing fb_var_screeninfo can affect fb_fix_screeninfo,
  146.     // so this needs done before querying for fi.
  147.     printf("Forcing pixel format: RGB_565\n");
  148.     vi.blue.offset    = 0;
  149.     vi.green.offset   = 5;
  150.     vi.red.offset     = 11;
  151.     vi.blue.length    = 5;
  152.     vi.green.length   = 6;
  153.     vi.red.length     = 5;
  154.     vi.blue.msb_right = 0;
  155.     vi.green.msb_right = 0;
  156.     vi.red.msb_right = 0;
  157.     vi.transp.offset  = 0;
  158.     vi.transp.length  = 0;
  159.     vi.bits_per_pixel = 16;
  160.  
  161.     if (ioctl(fd, FBIOPUT_VSCREENINFO, &vi) < 0) {
  162.         perror("failed to put force_rgb_565 fb0 info");
  163.         close(fd);
  164.         return NULL;
  165.     }
  166. #endif
  167.  
  168.     fb_fix_screeninfo fi;
  169.     if (ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) {
  170.         perror("failed to get fb0 info (FBIOGET_FSCREENINFO)");
  171.         close(fd);
  172.         return NULL;
  173.     }
  174.  
  175.     // We print this out for informational purposes only, but
  176.     // throughout we assume that the framebuffer device uses an RGBX
  177.     // pixel format.  This is the case for every development device I
  178.     // have access to.  For some of those devices (eg, hammerhead aka
  179.     // Nexus 5), FBIOGET_VSCREENINFO *reports* that it wants a
  180.     // different format (XBGR) but actually produces the correct
  181.     // results on the display when you write RGBX.
  182.     //
  183.     // If you have a device that actually *needs* another pixel format
  184.     // (ie, BGRX, or 565), patches welcome...
  185.  
  186.     printf("fb0 reports (possibly inaccurate):\n"
  187.            "  vi.bits_per_pixel = %d\n"
  188.            "  vi.red.offset   = %3d   .length = %3d\n"
  189.            "  vi.green.offset = %3d   .length = %3d\n"
  190.            "  vi.blue.offset  = %3d   .length = %3d\n",
  191.            vi.bits_per_pixel,
  192.            vi.red.offset, vi.red.length,
  193.            vi.green.offset, vi.green.length,
  194.            vi.blue.offset, vi.blue.length);
  195.  
  196.     void* bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  197.     if (bits == MAP_FAILED) {
  198.         perror("failed to mmap framebuffer");
  199.         close(fd);
  200.         return NULL;
  201.     }
  202.  
  203.     memset(bits, 0, fi.smem_len);
  204.  
  205.     gr_framebuffer[0].width = vi.xres;
  206.     gr_framebuffer[0].height = vi.yres;
  207.     gr_framebuffer[0].row_bytes = fi.line_length;
  208.     gr_framebuffer[0].pixel_bytes = vi.bits_per_pixel / 8;
  209. #ifdef RECOVERY_GRAPHICS_FORCE_USE_LINELENGTH
  210.     printf("Forcing line length\n");
  211.     vi.xres_virtual = fi.line_length / gr_framebuffer[0].pixel_bytes;
  212. #endif
  213.     gr_framebuffer[0].data = reinterpret_cast<uint8_t*>(bits);
  214.     if (vi.bits_per_pixel == 16) {
  215.         printf("setting GGL_PIXEL_FORMAT_RGB_565\n");
  216.         gr_framebuffer[0].format = GGL_PIXEL_FORMAT_RGB_565;
  217.     } else if (vi.red.offset == 8 || vi.red.offset == 16) {
  218.         printf("setting GGL_PIXEL_FORMAT_BGRA_8888\n");
  219.         gr_framebuffer[0].format = GGL_PIXEL_FORMAT_BGRA_8888;
  220.     } else if (vi.red.offset == 0) {
  221.         printf("setting GGL_PIXEL_FORMAT_RGBA_8888\n");
  222.         gr_framebuffer[0].format = GGL_PIXEL_FORMAT_RGBA_8888;
  223.     } else if (vi.red.offset == 24) {
  224.         printf("setting GGL_PIXEL_FORMAT_RGBX_8888\n");
  225.         gr_framebuffer[0].format = GGL_PIXEL_FORMAT_RGBX_8888;
  226.     } else {
  227.         if (vi.red.length == 8) {
  228.             printf("No valid pixel format detected, trying GGL_PIXEL_FORMAT_RGBX_8888\n");
  229.             gr_framebuffer[0].format = GGL_PIXEL_FORMAT_RGBX_8888;
  230.         } else {
  231.             printf("No valid pixel format detected, trying GGL_PIXEL_FORMAT_RGB_565\n");
  232.             gr_framebuffer[0].format = GGL_PIXEL_FORMAT_RGB_565;
  233.         }
  234.     }
  235.  
  236.     // Drawing directly to the framebuffer takes about 5 times longer.
  237.     // Instead, we will allocate some memory and draw to that, then
  238.     // memcpy the data into the framebuffer later.
  239.     gr_draw = (GRSurface*) malloc(sizeof(GRSurface));
  240.     if (!gr_draw) {
  241.         perror("failed to allocate gr_draw");
  242.         close(fd);
  243.         munmap(bits, fi.smem_len);
  244.         return NULL;
  245.     }
  246.     memcpy(gr_draw, gr_framebuffer, sizeof(GRSurface));
  247.     gr_draw->data = (unsigned char*) calloc(gr_draw->height * gr_draw->row_bytes, 1);
  248.     if (!gr_draw->data) {
  249.         perror("failed to allocate in-memory surface");
  250.         close(fd);
  251.         free(gr_draw);
  252.         munmap(bits, fi.smem_len);
  253.         return NULL;
  254.     }
  255.  
  256.     /* check if we can use double buffering */
  257. #ifndef RECOVERY_GRAPHICS_FORCE_SINGLE_BUFFER
  258.     if (vi.yres * fi.line_length * 2 <= fi.smem_len) {
  259.         double_buffered = true;
  260.         printf("double buffered\n");
  261.  
  262.         memcpy(gr_framebuffer+1, gr_framebuffer, sizeof(GRSurface));
  263.         gr_framebuffer[1].data = gr_framebuffer[0].data +
  264.             gr_framebuffer[0].height * gr_framebuffer[0].row_bytes;
  265.  
  266.     } else {
  267. #else
  268.     {
  269.         printf("RECOVERY_GRAPHICS_FORCE_SINGLE_BUFFER := true\n");
  270. #endif
  271.         double_buffered = false;
  272.         printf("single buffered\n");
  273.     }
  274. #if defined(RECOVERY_BGRA)
  275.     printf("RECOVERY_BGRA\n");
  276. #endif
  277.     fb_fd = fd;
  278.     set_displayed_framebuffer(0);
  279.  
  280.     printf("framebuffer: %d (%d x %d)\n", fb_fd, gr_draw->width, gr_draw->height);
  281.  
  282.     fbdev_blank(backend, true);
  283.     fbdev_blank(backend, false);
  284.  
  285.     smem_len = fi.smem_len;
  286.  
  287.     return gr_draw;
  288. }
  289.  
  290. static GRSurface* fbdev_flip(minui_backend* backend __unused) {
  291. #if defined(RECOVERY_BGRA)
  292.     // In case of BGRA, do some byte swapping
  293.     unsigned int idx;
  294.     unsigned char tmp;
  295.     unsigned char* ucfb_vaddr = (unsigned char*)gr_draw->data;
  296.     for (idx = 0 ; idx < (gr_draw->height * gr_draw->row_bytes);
  297.             idx += 4) {
  298.         tmp = ucfb_vaddr[idx];
  299.         ucfb_vaddr[idx    ] = ucfb_vaddr[idx + 2];
  300.         ucfb_vaddr[idx + 2] = tmp;
  301.     }
  302. #endif
  303. #ifndef BOARD_HAS_FLIPPED_SCREEN
  304.     if (double_buffered) {
  305.         // Copy from the in-memory surface to the framebuffer.
  306.         memcpy(gr_framebuffer[1-displayed_buffer].data, gr_draw->data,
  307.                gr_draw->height * gr_draw->row_bytes);
  308.         set_displayed_framebuffer(1-displayed_buffer);
  309.     } else {
  310.         // Copy from the in-memory surface to the framebuffer.
  311.         memcpy(gr_framebuffer[0].data, gr_draw->data,
  312.                gr_draw->height * gr_draw->row_bytes);
  313.     }
  314. #else
  315.     int gr_active_fb = 0;
  316.     if (double_buffered)
  317.         gr_active_fb = 1-displayed_buffer;
  318.  
  319.     /* flip buffer 180 degrees for devices with physically inverted screens */
  320.     unsigned int row_pixels = gr_draw->row_bytes / gr_framebuffer[0].pixel_bytes;
  321.     if (gr_framebuffer[0].pixel_bytes == 4) {
  322.         for (unsigned int y = 0; y < gr_draw->height; ++y) {
  323.             uint32_t* dst = reinterpret_cast<uint32_t*>(gr_framebuffer[gr_active_fb].data) + y * row_pixels;
  324.             uint32_t* src = reinterpret_cast<uint32_t*>(gr_draw->data) + (gr_draw->height - y - 1) * row_pixels + gr_draw->width;
  325.             for (unsigned int x = 0; x < gr_draw->width; ++x)
  326.                 *(dst++) = *(--src);
  327.         }
  328.     } else {
  329.         for (unsigned int y = 0; y < gr_draw->height; ++y) {
  330.             uint16_t* dst = reinterpret_cast<uint16_t*>(gr_framebuffer[gr_active_fb].data) + y * row_pixels;
  331.             uint16_t* src = reinterpret_cast<uint16_t*>(gr_draw->data) + (gr_draw->height - y - 1) * row_pixels + gr_draw->width;
  332.             for (unsigned int x = 0; x < gr_draw->width; ++x)
  333.                  *(dst++) = *(--src);
  334.         }
  335.     }
  336.  
  337.     if (double_buffered)
  338.         set_displayed_framebuffer(1-displayed_buffer);
  339. #endif
  340.     return gr_draw;
  341. }
  342.  
  343. static void fbdev_exit(minui_backend* backend __unused) {
  344.     close(fb_fd);
  345.     fb_fd = -1;
  346.  
  347.     if (gr_draw) {
  348.         free(gr_draw->data);
  349.         free(gr_draw);
  350.     }
  351.     gr_draw = NULL;
  352.     munmap(gr_framebuffer[0].data, smem_len);
  353. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement