vkms_plane.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2 of the License, or
  6. * (at your option) any later version.
  7. */
  8. #include "vkms_drv.h"
  9. #include <drm/drm_plane_helper.h>
  10. #include <drm/drm_atomic.h>
  11. #include <drm/drm_atomic_helper.h>
  12. #include <drm/drm_gem_framebuffer_helper.h>
  13. static struct drm_plane_state *
  14. vkms_plane_duplicate_state(struct drm_plane *plane)
  15. {
  16. struct vkms_plane_state *vkms_state;
  17. struct vkms_crc_data *crc_data;
  18. vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL);
  19. if (!vkms_state)
  20. return NULL;
  21. crc_data = kzalloc(sizeof(*crc_data), GFP_KERNEL);
  22. if (WARN_ON(!crc_data))
  23. DRM_INFO("Couldn't allocate crc_data");
  24. vkms_state->crc_data = crc_data;
  25. __drm_atomic_helper_plane_duplicate_state(plane,
  26. &vkms_state->base);
  27. return &vkms_state->base;
  28. }
  29. static void vkms_plane_destroy_state(struct drm_plane *plane,
  30. struct drm_plane_state *old_state)
  31. {
  32. struct vkms_plane_state *vkms_state = to_vkms_plane_state(old_state);
  33. struct drm_crtc *crtc = vkms_state->base.crtc;
  34. if (crtc) {
  35. /* dropping the reference we acquired in
  36. * vkms_primary_plane_update()
  37. */
  38. if (drm_framebuffer_read_refcount(&vkms_state->crc_data->fb))
  39. drm_framebuffer_put(&vkms_state->crc_data->fb);
  40. }
  41. kfree(vkms_state->crc_data);
  42. vkms_state->crc_data = NULL;
  43. __drm_atomic_helper_plane_destroy_state(old_state);
  44. kfree(vkms_state);
  45. }
  46. static void vkms_plane_reset(struct drm_plane *plane)
  47. {
  48. struct vkms_plane_state *vkms_state;
  49. if (plane->state)
  50. vkms_plane_destroy_state(plane, plane->state);
  51. vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL);
  52. if (!vkms_state) {
  53. DRM_ERROR("Cannot allocate vkms_plane_state\n");
  54. return;
  55. }
  56. plane->state = &vkms_state->base;
  57. plane->state->plane = plane;
  58. }
  59. static const struct drm_plane_funcs vkms_plane_funcs = {
  60. .update_plane = drm_atomic_helper_update_plane,
  61. .disable_plane = drm_atomic_helper_disable_plane,
  62. .destroy = drm_plane_cleanup,
  63. .reset = vkms_plane_reset,
  64. .atomic_duplicate_state = vkms_plane_duplicate_state,
  65. .atomic_destroy_state = vkms_plane_destroy_state,
  66. };
  67. static void vkms_plane_atomic_update(struct drm_plane *plane,
  68. struct drm_plane_state *old_state)
  69. {
  70. struct vkms_plane_state *vkms_plane_state;
  71. struct drm_framebuffer *fb = plane->state->fb;
  72. struct vkms_crc_data *crc_data;
  73. if (!plane->state->crtc || !fb)
  74. return;
  75. vkms_plane_state = to_vkms_plane_state(plane->state);
  76. crc_data = vkms_plane_state->crc_data;
  77. memcpy(&crc_data->src, &plane->state->src, sizeof(struct drm_rect));
  78. memcpy(&crc_data->dst, &plane->state->dst, sizeof(struct drm_rect));
  79. memcpy(&crc_data->fb, fb, sizeof(struct drm_framebuffer));
  80. drm_framebuffer_get(&crc_data->fb);
  81. crc_data->offset = fb->offsets[0];
  82. crc_data->pitch = fb->pitches[0];
  83. crc_data->cpp = fb->format->cpp[0];
  84. }
  85. static int vkms_plane_atomic_check(struct drm_plane *plane,
  86. struct drm_plane_state *state)
  87. {
  88. struct drm_crtc_state *crtc_state;
  89. bool can_position = false;
  90. int ret;
  91. if (!state->fb | !state->crtc)
  92. return 0;
  93. crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
  94. if (IS_ERR(crtc_state))
  95. return PTR_ERR(crtc_state);
  96. if (plane->type == DRM_PLANE_TYPE_CURSOR)
  97. can_position = true;
  98. ret = drm_atomic_helper_check_plane_state(state, crtc_state,
  99. DRM_PLANE_HELPER_NO_SCALING,
  100. DRM_PLANE_HELPER_NO_SCALING,
  101. can_position, true);
  102. if (ret != 0)
  103. return ret;
  104. /* for now primary plane must be visible and full screen */
  105. if (!state->visible && !can_position)
  106. return -EINVAL;
  107. return 0;
  108. }
  109. static int vkms_prepare_fb(struct drm_plane *plane,
  110. struct drm_plane_state *state)
  111. {
  112. struct drm_gem_object *gem_obj;
  113. struct vkms_gem_object *vkms_obj;
  114. int ret;
  115. if (!state->fb)
  116. return 0;
  117. gem_obj = drm_gem_fb_get_obj(state->fb, 0);
  118. vkms_obj = drm_gem_to_vkms_gem(gem_obj);
  119. ret = vkms_gem_vmap(gem_obj);
  120. if (ret)
  121. DRM_ERROR("vmap failed: %d\n", ret);
  122. return drm_gem_fb_prepare_fb(plane, state);
  123. }
  124. static void vkms_cleanup_fb(struct drm_plane *plane,
  125. struct drm_plane_state *old_state)
  126. {
  127. struct drm_gem_object *gem_obj;
  128. if (!old_state->fb)
  129. return;
  130. gem_obj = drm_gem_fb_get_obj(old_state->fb, 0);
  131. vkms_gem_vunmap(gem_obj);
  132. }
  133. static const struct drm_plane_helper_funcs vkms_primary_helper_funcs = {
  134. .atomic_update = vkms_plane_atomic_update,
  135. .atomic_check = vkms_plane_atomic_check,
  136. .prepare_fb = vkms_prepare_fb,
  137. .cleanup_fb = vkms_cleanup_fb,
  138. };
  139. struct drm_plane *vkms_plane_init(struct vkms_device *vkmsdev,
  140. enum drm_plane_type type)
  141. {
  142. struct drm_device *dev = &vkmsdev->drm;
  143. const struct drm_plane_helper_funcs *funcs;
  144. struct drm_plane *plane;
  145. const u32 *formats;
  146. int ret, nformats;
  147. plane = kzalloc(sizeof(*plane), GFP_KERNEL);
  148. if (!plane)
  149. return ERR_PTR(-ENOMEM);
  150. if (type == DRM_PLANE_TYPE_CURSOR) {
  151. formats = vkms_cursor_formats;
  152. nformats = ARRAY_SIZE(vkms_cursor_formats);
  153. funcs = &vkms_primary_helper_funcs;
  154. } else {
  155. formats = vkms_formats;
  156. nformats = ARRAY_SIZE(vkms_formats);
  157. funcs = &vkms_primary_helper_funcs;
  158. }
  159. ret = drm_universal_plane_init(dev, plane, 0,
  160. &vkms_plane_funcs,
  161. formats, nformats,
  162. NULL, type, NULL);
  163. if (ret) {
  164. kfree(plane);
  165. return ERR_PTR(ret);
  166. }
  167. drm_plane_helper_add(plane, funcs);
  168. return plane;
  169. }