hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/gpu/drm/virtio/virtgpu_plane.c
....@@ -23,9 +23,12 @@
2323 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2424 */
2525
26
-#include "virtgpu_drv.h"
27
-#include <drm/drm_plane_helper.h>
2826 #include <drm/drm_atomic_helper.h>
27
+#include <drm/drm_damage_helper.h>
28
+#include <drm/drm_fourcc.h>
29
+#include <drm/drm_plane_helper.h>
30
+
31
+#include "virtgpu_drv.h"
2932
3033 static const uint32_t virtio_gpu_formats[] = {
3134 DRM_FORMAT_XRGB8888,
....@@ -39,11 +42,7 @@
3942 };
4043
4144 static const uint32_t virtio_gpu_cursor_formats[] = {
42
-#ifdef __BIG_ENDIAN
43
- DRM_FORMAT_BGRA8888,
44
-#else
45
- DRM_FORMAT_ARGB8888,
46
-#endif
45
+ DRM_FORMAT_HOST_ARGB8888,
4746 };
4847
4948 uint32_t virtio_gpu_translate_format(uint32_t drm_fourcc)
....@@ -132,7 +131,45 @@
132131 static int virtio_gpu_plane_atomic_check(struct drm_plane *plane,
133132 struct drm_plane_state *state)
134133 {
135
- return 0;
134
+ bool is_cursor = plane->type == DRM_PLANE_TYPE_CURSOR;
135
+ struct drm_crtc_state *crtc_state;
136
+ int ret;
137
+
138
+ if (!state->fb || WARN_ON(!state->crtc))
139
+ return 0;
140
+
141
+ crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
142
+ if (IS_ERR(crtc_state))
143
+ return PTR_ERR(crtc_state);
144
+
145
+ ret = drm_atomic_helper_check_plane_state(state, crtc_state,
146
+ DRM_PLANE_HELPER_NO_SCALING,
147
+ DRM_PLANE_HELPER_NO_SCALING,
148
+ is_cursor, true);
149
+ return ret;
150
+}
151
+
152
+static void virtio_gpu_update_dumb_bo(struct virtio_gpu_device *vgdev,
153
+ struct drm_plane_state *state,
154
+ struct drm_rect *rect)
155
+{
156
+ struct virtio_gpu_object *bo =
157
+ gem_to_virtio_gpu_obj(state->fb->obj[0]);
158
+ struct virtio_gpu_object_array *objs;
159
+ uint32_t w = rect->x2 - rect->x1;
160
+ uint32_t h = rect->y2 - rect->y1;
161
+ uint32_t x = rect->x1;
162
+ uint32_t y = rect->y1;
163
+ uint32_t off = x * state->fb->format->cpp[0] +
164
+ y * state->fb->pitches[0];
165
+
166
+ objs = virtio_gpu_array_alloc(1);
167
+ if (!objs)
168
+ return;
169
+ virtio_gpu_array_add_obj(objs, &bo->base.base);
170
+
171
+ virtio_gpu_cmd_transfer_to_host_2d(vgdev, off, w, h, x, y,
172
+ objs, NULL);
136173 }
137174
138175 static void virtio_gpu_primary_plane_update(struct drm_plane *plane,
....@@ -141,9 +178,8 @@
141178 struct drm_device *dev = plane->dev;
142179 struct virtio_gpu_device *vgdev = dev->dev_private;
143180 struct virtio_gpu_output *output = NULL;
144
- struct virtio_gpu_framebuffer *vgfb;
145181 struct virtio_gpu_object *bo;
146
- uint32_t handle;
182
+ struct drm_rect rect;
147183
148184 if (plane->state->crtc)
149185 output = drm_crtc_to_virtio_gpu_output(plane->state->crtc);
....@@ -152,40 +188,52 @@
152188 if (WARN_ON(!output))
153189 return;
154190
155
- if (plane->state->fb && output->enabled) {
156
- vgfb = to_virtio_gpu_framebuffer(plane->state->fb);
157
- bo = gem_to_virtio_gpu_obj(vgfb->base.obj[0]);
158
- handle = bo->hw_res_handle;
159
- if (bo->dumb) {
160
- virtio_gpu_cmd_transfer_to_host_2d
161
- (vgdev, bo, 0,
162
- cpu_to_le32(plane->state->src_w >> 16),
163
- cpu_to_le32(plane->state->src_h >> 16),
164
- cpu_to_le32(plane->state->src_x >> 16),
165
- cpu_to_le32(plane->state->src_y >> 16), NULL);
166
- }
167
- } else {
168
- handle = 0;
191
+ if (!plane->state->fb || !output->crtc.state->active) {
192
+ DRM_DEBUG("nofb\n");
193
+ virtio_gpu_cmd_set_scanout(vgdev, output->index, 0,
194
+ plane->state->src_w >> 16,
195
+ plane->state->src_h >> 16,
196
+ 0, 0);
197
+ virtio_gpu_notify(vgdev);
198
+ return;
169199 }
170200
171
- DRM_DEBUG("handle 0x%x, crtc %dx%d+%d+%d, src %dx%d+%d+%d\n", handle,
172
- plane->state->crtc_w, plane->state->crtc_h,
173
- plane->state->crtc_x, plane->state->crtc_y,
174
- plane->state->src_w >> 16,
175
- plane->state->src_h >> 16,
176
- plane->state->src_x >> 16,
177
- plane->state->src_y >> 16);
178
- virtio_gpu_cmd_set_scanout(vgdev, output->index, handle,
179
- plane->state->src_w >> 16,
180
- plane->state->src_h >> 16,
181
- plane->state->src_x >> 16,
182
- plane->state->src_y >> 16);
183
- if (handle)
184
- virtio_gpu_cmd_resource_flush(vgdev, handle,
185
- plane->state->src_x >> 16,
186
- plane->state->src_y >> 16,
187
- plane->state->src_w >> 16,
188
- plane->state->src_h >> 16);
201
+ if (!drm_atomic_helper_damage_merged(old_state, plane->state, &rect))
202
+ return;
203
+
204
+ bo = gem_to_virtio_gpu_obj(plane->state->fb->obj[0]);
205
+ if (bo->dumb)
206
+ virtio_gpu_update_dumb_bo(vgdev, plane->state, &rect);
207
+
208
+ if (plane->state->fb != old_state->fb ||
209
+ plane->state->src_w != old_state->src_w ||
210
+ plane->state->src_h != old_state->src_h ||
211
+ plane->state->src_x != old_state->src_x ||
212
+ plane->state->src_y != old_state->src_y ||
213
+ output->needs_modeset) {
214
+ output->needs_modeset = false;
215
+ DRM_DEBUG("handle 0x%x, crtc %dx%d+%d+%d, src %dx%d+%d+%d\n",
216
+ bo->hw_res_handle,
217
+ plane->state->crtc_w, plane->state->crtc_h,
218
+ plane->state->crtc_x, plane->state->crtc_y,
219
+ plane->state->src_w >> 16,
220
+ plane->state->src_h >> 16,
221
+ plane->state->src_x >> 16,
222
+ plane->state->src_y >> 16);
223
+ virtio_gpu_cmd_set_scanout(vgdev, output->index,
224
+ bo->hw_res_handle,
225
+ plane->state->src_w >> 16,
226
+ plane->state->src_h >> 16,
227
+ plane->state->src_x >> 16,
228
+ plane->state->src_y >> 16);
229
+ }
230
+
231
+ virtio_gpu_cmd_resource_flush(vgdev, bo->hw_res_handle,
232
+ rect.x1,
233
+ rect.y1,
234
+ rect.x2 - rect.x1,
235
+ rect.y2 - rect.y1);
236
+ virtio_gpu_notify(vgdev);
189237 }
190238
191239 static int virtio_gpu_cursor_prepare_fb(struct drm_plane *plane,
....@@ -211,14 +259,14 @@
211259 }
212260
213261 static void virtio_gpu_cursor_cleanup_fb(struct drm_plane *plane,
214
- struct drm_plane_state *old_state)
262
+ struct drm_plane_state *state)
215263 {
216264 struct virtio_gpu_framebuffer *vgfb;
217265
218
- if (!plane->state->fb)
266
+ if (!state->fb)
219267 return;
220268
221
- vgfb = to_virtio_gpu_framebuffer(plane->state->fb);
269
+ vgfb = to_virtio_gpu_framebuffer(state->fb);
222270 if (vgfb->fence) {
223271 dma_fence_put(&vgfb->fence->f);
224272 vgfb->fence = NULL;
....@@ -234,7 +282,6 @@
234282 struct virtio_gpu_framebuffer *vgfb;
235283 struct virtio_gpu_object *bo = NULL;
236284 uint32_t handle;
237
- int ret = 0;
238285
239286 if (plane->state->crtc)
240287 output = drm_crtc_to_virtio_gpu_output(plane->state->crtc);
....@@ -253,20 +300,22 @@
253300
254301 if (bo && bo->dumb && (plane->state->fb != old_state->fb)) {
255302 /* new cursor -- update & wait */
303
+ struct virtio_gpu_object_array *objs;
304
+
305
+ objs = virtio_gpu_array_alloc(1);
306
+ if (!objs)
307
+ return;
308
+ virtio_gpu_array_add_obj(objs, vgfb->base.obj[0]);
309
+ virtio_gpu_array_lock_resv(objs);
256310 virtio_gpu_cmd_transfer_to_host_2d
257
- (vgdev, bo, 0,
258
- cpu_to_le32(plane->state->crtc_w),
259
- cpu_to_le32(plane->state->crtc_h),
260
- 0, 0, vgfb->fence);
261
- ret = virtio_gpu_object_reserve(bo, false);
262
- if (!ret) {
263
- reservation_object_add_excl_fence(bo->tbo.resv,
264
- &vgfb->fence->f);
265
- dma_fence_put(&vgfb->fence->f);
266
- vgfb->fence = NULL;
267
- virtio_gpu_object_unreserve(bo);
268
- virtio_gpu_object_wait(bo, false);
269
- }
311
+ (vgdev, 0,
312
+ plane->state->crtc_w,
313
+ plane->state->crtc_h,
314
+ 0, 0, objs, vgfb->fence);
315
+ virtio_gpu_notify(vgdev);
316
+ dma_fence_wait(&vgfb->fence->f, true);
317
+ dma_fence_put(&vgfb->fence->f);
318
+ vgfb->fence = NULL;
270319 }
271320
272321 if (plane->state->fb != old_state->fb) {