logo.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-02-25 GuEe-GUI the first version
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #include <rtdevice.h>
  13. #define DBG_TAG "graphic.logo"
  14. #define DBG_LVL DBG_INFO
  15. #include <rtdbg.h>
  16. #if __STARTUP_LOGO_WIDTH__ && __STARTUP_LOGO_HEIGHT__ && __STARTUP_LOGO_COLOR_MAX__
  17. static rt_uint8_t builtin_logo[] =
  18. {
  19. #include "logo.inc"
  20. };
  21. static void *startup_logo = builtin_logo;
  22. #else
  23. static void *startup_logo = RT_NULL;
  24. #endif
  25. static int startup_logo_width = __STARTUP_LOGO_WIDTH__;
  26. static int startup_logo_height = __STARTUP_LOGO_HEIGHT__;
  27. static int startup_logo_color_max = __STARTUP_LOGO_COLOR_MAX__;
  28. rt_err_t rt_graphic_logo_change(void *data, int width, int height, int color_max)
  29. {
  30. if (!data && !width && !height && !color_max)
  31. {
  32. /* Disable logo */
  33. startup_logo = RT_NULL;
  34. }
  35. else if (data && width > 0 && height > 0 && color_max > 0)
  36. {
  37. startup_logo = data;
  38. startup_logo_width = width;
  39. startup_logo_height = height;
  40. startup_logo_color_max = color_max;
  41. }
  42. else
  43. {
  44. return -RT_EINVAL;
  45. }
  46. return RT_EOK;
  47. }
  48. static rt_ubase_t to_grayscale(rt_ubase_t red, rt_ubase_t green, rt_ubase_t blue)
  49. {
  50. return (299 * red + 587 * green + 114 * blue) / 1000;
  51. }
  52. static rt_ubase_t to_color(rt_ubase_t color, rt_ubase_t in_color_max, rt_ubase_t out_color_max)
  53. {
  54. return color * out_color_max / in_color_max;
  55. }
  56. static rt_ubase_t gray_reordering(rt_ubase_t red, rt_ubase_t red_off,
  57. rt_ubase_t green, rt_ubase_t green_off,
  58. rt_ubase_t blue, rt_ubase_t blue_off,
  59. rt_ubase_t in_color_max, rt_ubase_t out_color_max)
  60. {
  61. return to_grayscale(to_color(red, in_color_max, out_color_max),
  62. to_color(green, in_color_max, out_color_max),
  63. to_color(blue, in_color_max, out_color_max));
  64. }
  65. static rt_ubase_t rgb_reordering(rt_ubase_t red, rt_ubase_t red_off,
  66. rt_ubase_t green, rt_ubase_t green_off,
  67. rt_ubase_t blue, rt_ubase_t blue_off,
  68. rt_ubase_t in_color_max, rt_ubase_t out_color_max)
  69. {
  70. return (to_color(red, in_color_max, out_color_max) << red_off) |
  71. (to_color(green, in_color_max, out_color_max) << green_off) |
  72. (to_color(blue, in_color_max, out_color_max) << blue_off);
  73. }
  74. rt_err_t rt_graphic_logo_render(struct rt_graphic_device *gdev)
  75. {
  76. rt_err_t err;
  77. int fb_color_max;
  78. rt_ubase_t xlate, none_alpha;
  79. rt_ubase_t red_off, green_off, blue_off;
  80. rt_ubase_t red_mask, green_mask, blue_mask;
  81. rt_uint8_t *logo, *fb, bytes_per_pixel;
  82. rt_ubase_t (*color_reordering)(rt_ubase_t, rt_ubase_t,
  83. rt_ubase_t, rt_ubase_t,
  84. rt_ubase_t, rt_ubase_t,
  85. rt_ubase_t, rt_ubase_t);
  86. struct fb_var_screeninfo var;
  87. struct rt_device_rect_info rect;
  88. struct rt_device_graphic_info info;
  89. struct rt_device *fbdev = &gdev->parent;
  90. if (!startup_logo)
  91. {
  92. return RT_EOK;
  93. }
  94. if ((err = rt_device_open(fbdev, 0)))
  95. {
  96. return err;
  97. }
  98. if ((err = rt_device_control(fbdev, FBIOGET_VSCREENINFO, &var)))
  99. {
  100. LOG_E("Get framebuffer %s error = %s", "var", rt_strerror(err));
  101. goto _close_fbdev;
  102. }
  103. if (startup_logo_width > var.xres || startup_logo_height > var.yres)
  104. {
  105. LOG_E("PPM logo[%u, %u] Out of screen[%u, %u]",
  106. startup_logo_width, startup_logo_height, var.xres, var.yres);
  107. err = -RT_EINVAL;
  108. goto _close_fbdev;
  109. }
  110. if ((err = rt_device_control(fbdev, RTGRAPHIC_CTRL_GET_INFO, &info)))
  111. {
  112. LOG_E("Get framebuffer %s error = %s", "info", rt_strerror(err));
  113. goto _close_fbdev;
  114. }
  115. if ((err = rt_device_control(fbdev, RTGRAPHIC_CTRL_POWERON, RT_NULL)))
  116. {
  117. LOG_E("Power on graphic device error = %s", rt_strerror(err));
  118. goto _close_fbdev;
  119. }
  120. if (var.grayscale)
  121. {
  122. color_reordering = &gray_reordering;
  123. }
  124. else
  125. {
  126. color_reordering = &rgb_reordering;
  127. }
  128. bytes_per_pixel = var.bits_per_pixel / 8;
  129. xlate = (var.xres - startup_logo_width) * bytes_per_pixel;
  130. rect.x = (var.xres - startup_logo_width) >> 1;
  131. rect.y = (var.yres - startup_logo_height) >> 1;
  132. rect.width = startup_logo_width,
  133. rect.height = startup_logo_height,
  134. fb = (void *)info.framebuffer;
  135. fb += rect.x * bytes_per_pixel + rect.y * info.pitch;
  136. logo = startup_logo;
  137. red_off = var.red.offset;
  138. red_mask = RT_GENMASK(var.red.length - 1, 0);
  139. green_off = var.green.offset;
  140. green_mask = RT_GENMASK(var.green.length - 1, 0);
  141. blue_off = var.blue.offset;
  142. blue_mask = RT_GENMASK(var.blue.length - 1, 0);
  143. fb_color_max = rt_max_t(int, rt_max_t(int, red_mask, green_mask), blue_mask);
  144. if (var.transp.length)
  145. {
  146. none_alpha = RT_GENMASK(var.transp.length - 1, 0) << var.transp.offset;
  147. }
  148. else
  149. {
  150. none_alpha = 0;
  151. }
  152. for (int dy = 0; dy < startup_logo_height; ++dy)
  153. {
  154. for (int dx = 0; dx < startup_logo_width; ++dx)
  155. {
  156. rt_ubase_t color = color_reordering(logo[0], red_off,
  157. logo[1], green_off,
  158. logo[2], blue_off,
  159. fb_color_max, startup_logo_color_max) |
  160. none_alpha;
  161. rt_memcpy(fb, &color, bytes_per_pixel);
  162. fb += bytes_per_pixel;
  163. logo += 3;
  164. }
  165. fb += xlate;
  166. }
  167. rt_device_control(fbdev, RTGRAPHIC_CTRL_RECT_UPDATE, &rect);
  168. rt_device_control(fbdev, RTGRAPHIC_CTRL_WAIT_VSYNC, RT_NULL);
  169. /* Complete */
  170. startup_logo = RT_NULL;
  171. /*
  172. * Should recycle here, logo takes up too much memory
  173. * if builtin is not RT_GRAPHIC_LOGO_NONE.
  174. */
  175. _close_fbdev:
  176. rt_device_close(fbdev);
  177. return err;
  178. }