vkms_plane.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. // SPDX-License-Identifier: GPL-2.0+
  2. #include <linux/iosys-map.h>
  3. #include <drm/drm_atomic.h>
  4. #include <drm/drm_atomic_helper.h>
  5. #include <drm/drm_blend.h>
  6. #include <drm/drm_fourcc.h>
  7. #include <drm/drm_gem_atomic_helper.h>
  8. #include <drm/drm_gem_framebuffer_helper.h>
  9. #include "vkms_drv.h"
  10. #include "vkms_formats.h"
  11. static const u32 vkms_formats[] = {
  12. DRM_FORMAT_ARGB8888,
  13. DRM_FORMAT_XRGB8888,
  14. DRM_FORMAT_XRGB16161616,
  15. DRM_FORMAT_ARGB16161616,
  16. DRM_FORMAT_RGB565
  17. };
  18. static struct drm_plane_state *
  19. vkms_plane_duplicate_state(struct drm_plane *plane)
  20. {
  21. struct vkms_plane_state *vkms_state;
  22. struct vkms_frame_info *frame_info;
  23. vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL);
  24. if (!vkms_state)
  25. return NULL;
  26. frame_info = kzalloc(sizeof(*frame_info), GFP_KERNEL);
  27. if (!frame_info) {
  28. DRM_DEBUG_KMS("Couldn't allocate frame_info\n");
  29. kfree(vkms_state);
  30. return NULL;
  31. }
  32. vkms_state->frame_info = frame_info;
  33. __drm_gem_duplicate_shadow_plane_state(plane, &vkms_state->base);
  34. return &vkms_state->base.base;
  35. }
  36. static void vkms_plane_destroy_state(struct drm_plane *plane,
  37. struct drm_plane_state *old_state)
  38. {
  39. struct vkms_plane_state *vkms_state = to_vkms_plane_state(old_state);
  40. struct drm_crtc *crtc = vkms_state->base.base.crtc;
  41. if (crtc && vkms_state->frame_info->fb) {
  42. /* dropping the reference we acquired in
  43. * vkms_primary_plane_update()
  44. */
  45. if (drm_framebuffer_read_refcount(vkms_state->frame_info->fb))
  46. drm_framebuffer_put(vkms_state->frame_info->fb);
  47. }
  48. kfree(vkms_state->frame_info);
  49. vkms_state->frame_info = NULL;
  50. __drm_gem_destroy_shadow_plane_state(&vkms_state->base);
  51. kfree(vkms_state);
  52. }
  53. static void vkms_plane_reset(struct drm_plane *plane)
  54. {
  55. struct vkms_plane_state *vkms_state;
  56. if (plane->state) {
  57. vkms_plane_destroy_state(plane, plane->state);
  58. plane->state = NULL; /* must be set to NULL here */
  59. }
  60. vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL);
  61. if (!vkms_state) {
  62. DRM_ERROR("Cannot allocate vkms_plane_state\n");
  63. return;
  64. }
  65. __drm_gem_reset_shadow_plane(plane, &vkms_state->base);
  66. }
  67. static const struct drm_plane_funcs vkms_plane_funcs = {
  68. .update_plane = drm_atomic_helper_update_plane,
  69. .disable_plane = drm_atomic_helper_disable_plane,
  70. .reset = vkms_plane_reset,
  71. .atomic_duplicate_state = vkms_plane_duplicate_state,
  72. .atomic_destroy_state = vkms_plane_destroy_state,
  73. };
  74. static void vkms_plane_atomic_update(struct drm_plane *plane,
  75. struct drm_atomic_state *state)
  76. {
  77. struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
  78. plane);
  79. struct vkms_plane_state *vkms_plane_state;
  80. struct drm_shadow_plane_state *shadow_plane_state;
  81. struct drm_framebuffer *fb = new_state->fb;
  82. struct vkms_frame_info *frame_info;
  83. u32 fmt;
  84. if (!new_state->crtc || !fb)
  85. return;
  86. fmt = fb->format->format;
  87. vkms_plane_state = to_vkms_plane_state(new_state);
  88. shadow_plane_state = &vkms_plane_state->base;
  89. frame_info = vkms_plane_state->frame_info;
  90. memcpy(&frame_info->src, &new_state->src, sizeof(struct drm_rect));
  91. memcpy(&frame_info->dst, &new_state->dst, sizeof(struct drm_rect));
  92. memcpy(&frame_info->rotated, &new_state->dst, sizeof(struct drm_rect));
  93. frame_info->fb = fb;
  94. memcpy(&frame_info->map, &shadow_plane_state->data, sizeof(frame_info->map));
  95. drm_framebuffer_get(frame_info->fb);
  96. frame_info->rotation = drm_rotation_simplify(new_state->rotation, DRM_MODE_ROTATE_0 |
  97. DRM_MODE_ROTATE_90 |
  98. DRM_MODE_ROTATE_270 |
  99. DRM_MODE_REFLECT_X |
  100. DRM_MODE_REFLECT_Y);
  101. drm_rect_rotate(&frame_info->rotated, drm_rect_width(&frame_info->rotated),
  102. drm_rect_height(&frame_info->rotated), frame_info->rotation);
  103. frame_info->offset = fb->offsets[0];
  104. frame_info->pitch = fb->pitches[0];
  105. frame_info->cpp = fb->format->cpp[0];
  106. vkms_plane_state->pixel_read = get_pixel_conversion_function(fmt);
  107. }
  108. static int vkms_plane_atomic_check(struct drm_plane *plane,
  109. struct drm_atomic_state *state)
  110. {
  111. struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
  112. plane);
  113. struct drm_crtc_state *crtc_state;
  114. int ret;
  115. if (!new_plane_state->fb || WARN_ON(!new_plane_state->crtc))
  116. return 0;
  117. crtc_state = drm_atomic_get_crtc_state(state,
  118. new_plane_state->crtc);
  119. if (IS_ERR(crtc_state))
  120. return PTR_ERR(crtc_state);
  121. ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
  122. DRM_PLANE_NO_SCALING,
  123. DRM_PLANE_NO_SCALING,
  124. true, true);
  125. if (ret != 0)
  126. return ret;
  127. return 0;
  128. }
  129. static int vkms_prepare_fb(struct drm_plane *plane,
  130. struct drm_plane_state *state)
  131. {
  132. struct drm_shadow_plane_state *shadow_plane_state;
  133. struct drm_framebuffer *fb = state->fb;
  134. int ret;
  135. if (!fb)
  136. return 0;
  137. shadow_plane_state = to_drm_shadow_plane_state(state);
  138. ret = drm_gem_plane_helper_prepare_fb(plane, state);
  139. if (ret)
  140. return ret;
  141. return drm_gem_fb_vmap(fb, shadow_plane_state->map, shadow_plane_state->data);
  142. }
  143. static void vkms_cleanup_fb(struct drm_plane *plane,
  144. struct drm_plane_state *state)
  145. {
  146. struct drm_shadow_plane_state *shadow_plane_state;
  147. struct drm_framebuffer *fb = state->fb;
  148. if (!fb)
  149. return;
  150. shadow_plane_state = to_drm_shadow_plane_state(state);
  151. drm_gem_fb_vunmap(fb, shadow_plane_state->map);
  152. }
  153. static const struct drm_plane_helper_funcs vkms_plane_helper_funcs = {
  154. .atomic_update = vkms_plane_atomic_update,
  155. .atomic_check = vkms_plane_atomic_check,
  156. .prepare_fb = vkms_prepare_fb,
  157. .cleanup_fb = vkms_cleanup_fb,
  158. };
  159. struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
  160. enum drm_plane_type type, int index)
  161. {
  162. struct drm_device *dev = &vkmsdev->drm;
  163. struct vkms_plane *plane;
  164. plane = drmm_universal_plane_alloc(dev, struct vkms_plane, base, 1 << index,
  165. &vkms_plane_funcs,
  166. vkms_formats, ARRAY_SIZE(vkms_formats),
  167. NULL, type, NULL);
  168. if (IS_ERR(plane))
  169. return plane;
  170. drm_plane_helper_add(&plane->base, &vkms_plane_helper_funcs);
  171. drm_plane_create_rotation_property(&plane->base, DRM_MODE_ROTATE_0,
  172. DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK);
  173. return plane;
  174. }