graphic_buffer.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /*
  2. * Copyright (c) 2020 Actions Technology Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #define LOG_MODULE_CUSTOMER
  7. #include <assert.h>
  8. #include <string.h>
  9. #include <memory/mem_cache.h>
  10. #include <display/display_hal.h>
  11. #include <display/graphic_buffer.h>
  12. LOG_MODULE_REGISTER(graphic_buf, LOG_LEVEL_INF);
  13. #define usage_sw(usage) (usage & GRAPHIC_BUFFER_SW_MASK)
  14. #define usage_sw_read(usage) (usage & GRAPHIC_BUFFER_SW_READ)
  15. #define usage_sw_write(usage) (usage & GRAPHIC_BUFFER_SW_WRITE)
  16. #define usage_hw(usage) (usage & GRAPHIC_BUFFER_HW_MASK)
  17. #define usage_hw_read(usage) (usage & (GRAPHIC_BUFFER_HW_TEXTURE | GRAPHIC_BUFFER_HW_COMPOSER))
  18. #define usage_hw_write(usage) (usage & GRAPHIC_BUFFER_HW_RENDER)
  19. #define usage_read(usage) (usage & GRAPHIC_BUFFER_READ_MASK)
  20. #define usage_write(usage) (usage & GRAPHIC_BUFFER_WRITE_MASK)
  21. int graphic_buffer_init(graphic_buffer_t *buffer, uint16_t w, uint16_t h,
  22. uint32_t pixel_format, uint32_t usage, uint16_t stride, void *data)
  23. {
  24. assert(buffer != NULL);
  25. memset(buffer, 0, sizeof(*buffer));
  26. buffer->width = w;
  27. buffer->height = h;
  28. buffer->stride = stride;
  29. buffer->bits_per_pixel = display_format_get_bits_per_pixel(pixel_format);
  30. buffer->pixel_format = pixel_format;
  31. buffer->data = data;
  32. buffer->usage = usage;
  33. atomic_set(&buffer->refcount, 1);
  34. return 0;
  35. }
  36. int graphic_buffer_ref(graphic_buffer_t *buffer)
  37. {
  38. assert(buffer != NULL);
  39. assert(atomic_get(&buffer->refcount) >= 0);
  40. return atomic_inc(&buffer->refcount);
  41. }
  42. int graphic_buffer_unref(graphic_buffer_t *buffer)
  43. {
  44. assert(buffer != NULL);
  45. assert(atomic_get(&buffer->refcount) > 0);
  46. int refcnt = atomic_dec(&buffer->refcount);
  47. if (refcnt == 1 && buffer->destroy_cb) {
  48. buffer->destroy_cb(buffer);
  49. }
  50. return refcnt;
  51. }
  52. const void *graphic_buffer_get_bufptr(graphic_buffer_t *buffer, int16_t x, int16_t y)
  53. {
  54. assert(buffer != NULL && buffer->data != NULL);
  55. return buffer->data + ((int32_t)y * buffer->stride + x) * buffer->bits_per_pixel / 8;
  56. }
  57. int graphic_buffer_lock(graphic_buffer_t *buffer, uint32_t usage,
  58. const ui_region_t *rect, void **vaddr)
  59. {
  60. assert(buffer != NULL);
  61. assert((usage & buffer->usage) == usage);
  62. if (usage_sw(usage) && !vaddr) {
  63. SYS_LOG_ERR("vaddr must provided");
  64. return -EINVAL;
  65. }
  66. if (usage_write(usage) && usage_write(buffer->lock_usage)) {
  67. SYS_LOG_ERR("multi-write disallowed");
  68. return -EINVAL;
  69. }
  70. if (usage_write(usage)) {
  71. if (rect) {
  72. memcpy(&buffer->lock_wrect, rect, sizeof(*rect));
  73. } else {
  74. buffer->lock_wrect.x1 = 0;
  75. buffer->lock_wrect.y1 = 0;
  76. buffer->lock_wrect.x2 = graphic_buffer_get_width(buffer) - 1;
  77. buffer->lock_wrect.y2 = graphic_buffer_get_height(buffer) - 1;
  78. }
  79. }
  80. if (vaddr) {
  81. *vaddr = buffer->data;
  82. if (rect) {
  83. *vaddr = (void *)graphic_buffer_get_bufptr(buffer, rect->x1, rect->y1);
  84. }
  85. }
  86. buffer->lock_usage |= usage;
  87. graphic_buffer_ref(buffer);
  88. return 0;
  89. }
  90. int graphic_buffer_unlock(graphic_buffer_t *buffer)
  91. {
  92. bool (*cache_ops)(const void *, uint32_t) = NULL;
  93. assert(buffer != NULL && buffer->lock_usage > 0);
  94. if (mem_is_cacheable(buffer->data) == false) {
  95. goto out_exit;
  96. }
  97. if (usage_sw_write(buffer->lock_usage) && usage_hw(buffer->usage)) {
  98. cache_ops = mem_dcache_clean;
  99. } else if (usage_hw_write(buffer->lock_usage) && usage_sw(buffer->usage)) {
  100. cache_ops = mem_dcache_flush;
  101. }
  102. if (cache_ops) {
  103. uint8_t *lock_vaddr = (uint8_t *)graphic_buffer_get_bufptr(buffer,
  104. buffer->lock_wrect.x1, buffer->lock_wrect.y1);
  105. uint16_t lock_w = ui_region_get_width(&buffer->lock_wrect);
  106. uint16_t lock_h = ui_region_get_height(&buffer->lock_wrect);
  107. uint16_t bytes_per_line = buffer->stride * buffer->bits_per_pixel / 8;
  108. uint16_t line_len = (lock_w * buffer->bits_per_pixel + 7) / 8;
  109. if (lock_w == buffer->width) {
  110. cache_ops(lock_vaddr, lock_h * bytes_per_line);
  111. } else {
  112. for (int i = lock_h; i > 0; i--) {
  113. cache_ops(lock_vaddr, line_len);
  114. lock_vaddr += bytes_per_line;
  115. }
  116. }
  117. mem_dcache_sync();
  118. }
  119. out_exit:
  120. buffer->lock_usage &= ~GRAPHIC_BUFFER_WRITE_MASK;
  121. graphic_buffer_unref(buffer);
  122. return 0;
  123. }
  124. void graphic_buffer_destroy(graphic_buffer_t *buffer)
  125. {
  126. graphic_buffer_unref(buffer);
  127. }