blob: 1ff9c64c9ec068f97ce54f9eaba6bf0bfde4ec62 [file] [log] [blame]
Dave Airliedc5698e2013-09-09 10:02:56 +10001/*
2 * Copyright (C) 2015 Red Hat, Inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26#include "virtgpu_drv.h"
27#include <drm/drm_plane_helper.h>
28#include <drm/drm_atomic_helper.h>
29
30static const uint32_t virtio_gpu_formats[] = {
31 DRM_FORMAT_XRGB8888,
32 DRM_FORMAT_ARGB8888,
33 DRM_FORMAT_BGRX8888,
34 DRM_FORMAT_BGRA8888,
35 DRM_FORMAT_RGBX8888,
36 DRM_FORMAT_RGBA8888,
37 DRM_FORMAT_XBGR8888,
38 DRM_FORMAT_ABGR8888,
39};
40
Gerd Hoffmannbbbed882016-05-26 11:42:52 +020041static const uint32_t virtio_gpu_cursor_formats[] = {
42 DRM_FORMAT_ARGB8888,
43};
44
Dave Airliedc5698e2013-09-09 10:02:56 +100045static void virtio_gpu_plane_destroy(struct drm_plane *plane)
46{
Gustavo Padovanfb700462017-02-15 16:00:08 -020047 drm_plane_cleanup(plane);
Dave Airliedc5698e2013-09-09 10:02:56 +100048 kfree(plane);
49}
50
51static const struct drm_plane_funcs virtio_gpu_plane_funcs = {
52 .update_plane = drm_atomic_helper_update_plane,
53 .disable_plane = drm_atomic_helper_disable_plane,
54 .destroy = virtio_gpu_plane_destroy,
55 .reset = drm_atomic_helper_plane_reset,
56 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
57 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
58};
59
60static int virtio_gpu_plane_atomic_check(struct drm_plane *plane,
61 struct drm_plane_state *state)
62{
63 return 0;
64}
65
Gerd Hoffmannbbbed882016-05-26 11:42:52 +020066static void virtio_gpu_primary_plane_update(struct drm_plane *plane,
67 struct drm_plane_state *old_state)
Dave Airliedc5698e2013-09-09 10:02:56 +100068{
69 struct drm_device *dev = plane->dev;
70 struct virtio_gpu_device *vgdev = dev->dev_private;
Gerd Hoffmannd3767d42016-05-27 14:20:24 +020071 struct virtio_gpu_output *output = NULL;
Dave Airliedc5698e2013-09-09 10:02:56 +100072 struct virtio_gpu_framebuffer *vgfb;
73 struct virtio_gpu_object *bo;
74 uint32_t handle;
75
Gerd Hoffmannd3767d42016-05-27 14:20:24 +020076 if (plane->state->crtc)
77 output = drm_crtc_to_virtio_gpu_output(plane->state->crtc);
78 if (old_state->crtc)
79 output = drm_crtc_to_virtio_gpu_output(old_state->crtc);
Heinrich Schuchardtb28c69d2016-08-21 23:06:06 +020080 if (WARN_ON(!output))
81 return;
Gerd Hoffmannd3767d42016-05-27 14:20:24 +020082
Rob Herring11c94ac2016-01-13 15:52:07 -060083 if (plane->state->fb) {
84 vgfb = to_virtio_gpu_framebuffer(plane->state->fb);
Dave Airliedc5698e2013-09-09 10:02:56 +100085 bo = gem_to_virtio_gpu_obj(vgfb->obj);
86 handle = bo->hw_res_handle;
Rob Herring4109e7f72016-01-13 15:52:09 -060087 if (bo->dumb) {
88 virtio_gpu_cmd_transfer_to_host_2d
89 (vgdev, handle, 0,
Gerd Hoffmann00627952016-05-31 14:20:22 +020090 cpu_to_le32(plane->state->src_w >> 16),
91 cpu_to_le32(plane->state->src_h >> 16),
Michael S. Tsirkin8854a562016-12-05 21:44:39 +020092 cpu_to_le32(plane->state->src_x >> 16),
93 cpu_to_le32(plane->state->src_y >> 16), NULL);
Rob Herring4109e7f72016-01-13 15:52:09 -060094 }
Dave Airliedc5698e2013-09-09 10:02:56 +100095 } else {
96 handle = 0;
97 }
98
Gerd Hoffmann00627952016-05-31 14:20:22 +020099 DRM_DEBUG("handle 0x%x, crtc %dx%d+%d+%d, src %dx%d+%d+%d\n", handle,
Dave Airliedc5698e2013-09-09 10:02:56 +1000100 plane->state->crtc_w, plane->state->crtc_h,
Gerd Hoffmann00627952016-05-31 14:20:22 +0200101 plane->state->crtc_x, plane->state->crtc_y,
102 plane->state->src_w >> 16,
103 plane->state->src_h >> 16,
104 plane->state->src_x >> 16,
105 plane->state->src_y >> 16);
Dave Airliedc5698e2013-09-09 10:02:56 +1000106 virtio_gpu_cmd_set_scanout(vgdev, output->index, handle,
Gerd Hoffmann00627952016-05-31 14:20:22 +0200107 plane->state->src_w >> 16,
108 plane->state->src_h >> 16,
109 plane->state->src_x >> 16,
110 plane->state->src_y >> 16);
Rob Herringbd17d1c2016-01-13 15:52:08 -0600111 virtio_gpu_cmd_resource_flush(vgdev, handle,
Gerd Hoffmann00627952016-05-31 14:20:22 +0200112 plane->state->src_x >> 16,
113 plane->state->src_y >> 16,
114 plane->state->src_w >> 16,
115 plane->state->src_h >> 16);
Dave Airliedc5698e2013-09-09 10:02:56 +1000116}
117
Gerd Hoffmannbbbed882016-05-26 11:42:52 +0200118static void virtio_gpu_cursor_plane_update(struct drm_plane *plane,
119 struct drm_plane_state *old_state)
120{
121 struct drm_device *dev = plane->dev;
122 struct virtio_gpu_device *vgdev = dev->dev_private;
123 struct virtio_gpu_output *output = NULL;
124 struct virtio_gpu_framebuffer *vgfb;
125 struct virtio_gpu_fence *fence = NULL;
126 struct virtio_gpu_object *bo = NULL;
127 uint32_t handle;
128 int ret = 0;
Dave Airliedc5698e2013-09-09 10:02:56 +1000129
Gerd Hoffmannbbbed882016-05-26 11:42:52 +0200130 if (plane->state->crtc)
131 output = drm_crtc_to_virtio_gpu_output(plane->state->crtc);
132 if (old_state->crtc)
133 output = drm_crtc_to_virtio_gpu_output(old_state->crtc);
Heinrich Schuchardtb28c69d2016-08-21 23:06:06 +0200134 if (WARN_ON(!output))
135 return;
Gerd Hoffmannbbbed882016-05-26 11:42:52 +0200136
137 if (plane->state->fb) {
138 vgfb = to_virtio_gpu_framebuffer(plane->state->fb);
139 bo = gem_to_virtio_gpu_obj(vgfb->obj);
140 handle = bo->hw_res_handle;
141 } else {
142 handle = 0;
143 }
144
145 if (bo && bo->dumb && (plane->state->fb != old_state->fb)) {
146 /* new cursor -- update & wait */
147 virtio_gpu_cmd_transfer_to_host_2d
148 (vgdev, handle, 0,
149 cpu_to_le32(plane->state->crtc_w),
150 cpu_to_le32(plane->state->crtc_h),
151 0, 0, &fence);
152 ret = virtio_gpu_object_reserve(bo, false);
153 if (!ret) {
154 reservation_object_add_excl_fence(bo->tbo.resv,
155 &fence->f);
Chris Wilsonf54d1862016-10-25 13:00:45 +0100156 dma_fence_put(&fence->f);
Gerd Hoffmannbbbed882016-05-26 11:42:52 +0200157 fence = NULL;
158 virtio_gpu_object_unreserve(bo);
159 virtio_gpu_object_wait(bo, false);
160 }
161 }
162
163 if (plane->state->fb != old_state->fb) {
Gerd Hoffmann86f752d2016-05-31 09:36:21 +0200164 DRM_DEBUG("update, handle %d, pos +%d+%d, hot %d,%d\n", handle,
Gerd Hoffmannbbbed882016-05-26 11:42:52 +0200165 plane->state->crtc_x,
Gerd Hoffmann86f752d2016-05-31 09:36:21 +0200166 plane->state->crtc_y,
167 plane->state->fb ? plane->state->fb->hot_x : 0,
168 plane->state->fb ? plane->state->fb->hot_y : 0);
Gerd Hoffmannbbbed882016-05-26 11:42:52 +0200169 output->cursor.hdr.type =
170 cpu_to_le32(VIRTIO_GPU_CMD_UPDATE_CURSOR);
171 output->cursor.resource_id = cpu_to_le32(handle);
Gerd Hoffmann86f752d2016-05-31 09:36:21 +0200172 if (plane->state->fb) {
173 output->cursor.hot_x =
174 cpu_to_le32(plane->state->fb->hot_x);
175 output->cursor.hot_y =
176 cpu_to_le32(plane->state->fb->hot_y);
177 } else {
178 output->cursor.hot_x = cpu_to_le32(0);
179 output->cursor.hot_y = cpu_to_le32(0);
180 }
Gerd Hoffmannbbbed882016-05-26 11:42:52 +0200181 } else {
182 DRM_DEBUG("move +%d+%d\n",
183 plane->state->crtc_x,
184 plane->state->crtc_y);
185 output->cursor.hdr.type =
186 cpu_to_le32(VIRTIO_GPU_CMD_MOVE_CURSOR);
187 }
188 output->cursor.pos.x = cpu_to_le32(plane->state->crtc_x);
189 output->cursor.pos.y = cpu_to_le32(plane->state->crtc_y);
190 virtio_gpu_cursor_ping(vgdev, output);
191}
192
193static const struct drm_plane_helper_funcs virtio_gpu_primary_helper_funcs = {
Dave Airliedc5698e2013-09-09 10:02:56 +1000194 .atomic_check = virtio_gpu_plane_atomic_check,
Gerd Hoffmannbbbed882016-05-26 11:42:52 +0200195 .atomic_update = virtio_gpu_primary_plane_update,
196};
197
198static const struct drm_plane_helper_funcs virtio_gpu_cursor_helper_funcs = {
199 .atomic_check = virtio_gpu_plane_atomic_check,
200 .atomic_update = virtio_gpu_cursor_plane_update,
Dave Airliedc5698e2013-09-09 10:02:56 +1000201};
202
203struct drm_plane *virtio_gpu_plane_init(struct virtio_gpu_device *vgdev,
Gerd Hoffmannbbbed882016-05-26 11:42:52 +0200204 enum drm_plane_type type,
Dave Airliedc5698e2013-09-09 10:02:56 +1000205 int index)
206{
207 struct drm_device *dev = vgdev->ddev;
Gerd Hoffmannbbbed882016-05-26 11:42:52 +0200208 const struct drm_plane_helper_funcs *funcs;
Dave Airliedc5698e2013-09-09 10:02:56 +1000209 struct drm_plane *plane;
Gerd Hoffmannbbbed882016-05-26 11:42:52 +0200210 const uint32_t *formats;
211 int ret, nformats;
Dave Airliedc5698e2013-09-09 10:02:56 +1000212
213 plane = kzalloc(sizeof(*plane), GFP_KERNEL);
214 if (!plane)
215 return ERR_PTR(-ENOMEM);
216
Gerd Hoffmannbbbed882016-05-26 11:42:52 +0200217 if (type == DRM_PLANE_TYPE_CURSOR) {
218 formats = virtio_gpu_cursor_formats;
219 nformats = ARRAY_SIZE(virtio_gpu_cursor_formats);
220 funcs = &virtio_gpu_cursor_helper_funcs;
221 } else {
222 formats = virtio_gpu_formats;
223 nformats = ARRAY_SIZE(virtio_gpu_formats);
224 funcs = &virtio_gpu_primary_helper_funcs;
225 }
Dave Airliedc5698e2013-09-09 10:02:56 +1000226 ret = drm_universal_plane_init(dev, plane, 1 << index,
227 &virtio_gpu_plane_funcs,
Gerd Hoffmannbbbed882016-05-26 11:42:52 +0200228 formats, nformats,
229 type, NULL);
Dave Airliedc5698e2013-09-09 10:02:56 +1000230 if (ret)
231 goto err_plane_init;
232
Gerd Hoffmannbbbed882016-05-26 11:42:52 +0200233 drm_plane_helper_add(plane, funcs);
Dave Airliedc5698e2013-09-09 10:02:56 +1000234 return plane;
235
236err_plane_init:
237 kfree(plane);
238 return ERR_PTR(ret);
239}