1 /*
2 * Copyright 2017 The Chromium OS Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
7 #include <assert.h>
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <pthread.h>
11 #include <stdatomic.h>
12 #include <stdint.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <sys/mman.h>
16 #include <unistd.h>
17 #include <xf86drm.h>
18
19 #include "drv_helpers.h"
20 #include "drv_priv.h"
21 #include "external/virgl_hw.h"
22 #include "external/virgl_protocol.h"
23 #include "external/virtgpu_drm.h"
24 #include "external/virtgpu_gfxstream_protocol.h"
25 #include "util.h"
26 #include "virtgpu.h"
27
28 #define PIPE_TEXTURE_2D 2
29
30 // This comes from a combination of SwiftShader's VkPhysicalDeviceLimits::maxFramebufferWidth and
31 // VkPhysicalDeviceLimits::maxImageDimension2D (see https://crrev.com/c/1917130).
32 #define ANGLE_ON_SWIFTSHADER_MAX_TEXTURE_2D_SIZE 8192
33
34 #ifndef MIN
35 #define MIN(a, b) ((a) < (b) ? (a) : (b))
36 #endif
37 #define VIRGL_2D_MAX_TEXTURE_2D_SIZE \
38 MIN(ANGLE_ON_SWIFTSHADER_MAX_TEXTURE_2D_SIZE, MESA_LLVMPIPE_MAX_TEXTURE_2D_SIZE)
39
40 static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888,
41 DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888,
42 DRM_FORMAT_XRGB8888 };
43
44 static const uint32_t dumb_texture_source_formats[] = {
45 DRM_FORMAT_R8, DRM_FORMAT_R16, DRM_FORMAT_YVU420,
46 DRM_FORMAT_NV12, DRM_FORMAT_NV21, DRM_FORMAT_YVU420_ANDROID,
47 DRM_FORMAT_ABGR2101010, DRM_FORMAT_ABGR16161616F
48 };
49
50 static const uint32_t texture_source_formats[] = {
51 DRM_FORMAT_NV12, DRM_FORMAT_NV21, DRM_FORMAT_R8,
52 DRM_FORMAT_R16, DRM_FORMAT_RG88, DRM_FORMAT_YVU420_ANDROID,
53 DRM_FORMAT_ABGR2101010, DRM_FORMAT_ABGR16161616F
54 };
55
56 static const uint32_t depth_stencil_formats[] = {
57 DRM_FORMAT_DEPTH16, DRM_FORMAT_DEPTH24, DRM_FORMAT_DEPTH24_STENCIL8,
58 DRM_FORMAT_DEPTH32, DRM_FORMAT_DEPTH32_STENCIL8
59 };
60
61 extern struct virtgpu_param params[];
62
63 struct virgl_blob_metadata_cache {
64 struct lru_entry entry;
65 struct bo_metadata meta;
66 };
67
68 #define lru_entry_to_metadata(entry) ((struct virgl_blob_metadata_cache *)(void *)(entry))
69
70 #define MAX_CACHED_FORMATS 128
71
72 struct virgl_priv {
73 int caps_is_v2;
74 union virgl_caps caps;
75 int caps_is_gfxstream;
76 struct vulkanCapset gfxstream_vulkan_caps;
77 int host_gbm_enabled;
78 atomic_int next_blob_id;
79
80 pthread_mutex_t host_blob_format_lock;
81 struct lru virgl_blob_metadata_cache;
82 };
83
translate_format(uint32_t drm_fourcc)84 static uint32_t translate_format(uint32_t drm_fourcc)
85 {
86 switch (drm_fourcc) {
87 case DRM_FORMAT_BGR888:
88 case DRM_FORMAT_RGB888:
89 return VIRGL_FORMAT_R8G8B8_UNORM;
90 case DRM_FORMAT_XRGB8888:
91 return VIRGL_FORMAT_B8G8R8X8_UNORM;
92 case DRM_FORMAT_ARGB8888:
93 return VIRGL_FORMAT_B8G8R8A8_UNORM;
94 case DRM_FORMAT_XBGR8888:
95 return VIRGL_FORMAT_R8G8B8X8_UNORM;
96 case DRM_FORMAT_ABGR8888:
97 return VIRGL_FORMAT_R8G8B8A8_UNORM;
98 case DRM_FORMAT_ABGR16161616F:
99 return VIRGL_FORMAT_R16G16B16A16_FLOAT;
100 case DRM_FORMAT_ABGR2101010:
101 return VIRGL_FORMAT_R10G10B10A2_UNORM;
102 case DRM_FORMAT_RGB565:
103 return VIRGL_FORMAT_B5G6R5_UNORM;
104 case DRM_FORMAT_R8:
105 return VIRGL_FORMAT_R8_UNORM;
106 case DRM_FORMAT_R16:
107 return VIRGL_FORMAT_R16_UNORM;
108 case DRM_FORMAT_RG88:
109 return VIRGL_FORMAT_R8G8_UNORM;
110 case DRM_FORMAT_NV12:
111 return VIRGL_FORMAT_NV12;
112 case DRM_FORMAT_NV21:
113 return VIRGL_FORMAT_NV21;
114 case DRM_FORMAT_P010:
115 return VIRGL_FORMAT_P010;
116 case DRM_FORMAT_YVU420:
117 case DRM_FORMAT_YVU420_ANDROID:
118 return VIRGL_FORMAT_YV12;
119 case DRM_FORMAT_DEPTH16:
120 return VIRGL_FORMAT_Z16_UNORM;
121 case DRM_FORMAT_DEPTH24:
122 return VIRGL_FORMAT_Z24X8_UNORM;
123 case DRM_FORMAT_DEPTH24_STENCIL8:
124 return VIRGL_FORMAT_Z24_UNORM_S8_UINT;
125 case DRM_FORMAT_DEPTH32:
126 return VIRGL_FORMAT_Z32_FLOAT;
127 case DRM_FORMAT_DEPTH32_STENCIL8:
128 return VIRGL_FORMAT_Z32_FLOAT_S8X24_UINT;
129 default:
130 drv_loge("Unhandled format:%d\n", drm_fourcc);
131 return 0;
132 }
133 }
134
virgl_bitmask_supports_format(struct virgl_supported_format_mask * supported,uint32_t drm_format)135 static bool virgl_bitmask_supports_format(struct virgl_supported_format_mask *supported,
136 uint32_t drm_format)
137 {
138 uint32_t virgl_format = translate_format(drm_format);
139 if (!virgl_format)
140 return false;
141
142 uint32_t bitmask_index = virgl_format / 32;
143 uint32_t bit_index = virgl_format % 32;
144 return supported->bitmask[bitmask_index] & (1 << bit_index);
145 }
146
147 // The metadata generated here for emulated buffers is slightly different than the metadata
148 // generated by drv_bo_from_format. In order to simplify transfers in the flush and invalidate
149 // functions below, the emulated buffers are oversized. For example, ignoring stride alignment
150 // requirements to demonstrate, a 6x6 YUV420 image buffer might have the following layout from
151 // drv_bo_from_format:
152 //
153 // | Y | Y | Y | Y | Y | Y |
154 // | Y | Y | Y | Y | Y | Y |
155 // | Y | Y | Y | Y | Y | Y |
156 // | Y | Y | Y | Y | Y | Y |
157 // | Y | Y | Y | Y | Y | Y |
158 // | Y | Y | Y | Y | Y | Y |
159 // | U | U | U | U | U | U |
160 // | U | U | U | V | V | V |
161 // | V | V | V | V | V | V |
162 //
163 // where each plane immediately follows the previous plane in memory. This layout makes it
164 // difficult to compute the transfers needed for example when the middle 2x2 region of the
165 // image is locked and needs to be flushed/invalidated.
166 //
167 // Emulated multi-plane buffers instead have a layout of:
168 //
169 // | Y | Y | Y | Y | Y | Y |
170 // | Y | Y | Y | Y | Y | Y |
171 // | Y | Y | Y | Y | Y | Y |
172 // | Y | Y | Y | Y | Y | Y |
173 // | Y | Y | Y | Y | Y | Y |
174 // | Y | Y | Y | Y | Y | Y |
175 // | U | U | U | | | |
176 // | U | U | U | | | |
177 // | U | U | U | | | |
178 // | V | V | V | | | |
179 // | V | V | V | | | |
180 // | V | V | V | | | |
181 //
182 // where each plane is placed as a sub-image (albeit with a very large stride) in order to
183 // simplify transfers into 3 sub-image transfers for the above example.
184 //
185 // Additional note: the V-plane is not placed to the right of the U-plane due to some
186 // observed failures in media framework code which assumes the V-plane is not
187 // "row-interlaced" with the U-plane.
virgl_get_emulated_metadata(const struct bo * bo,struct bo_metadata * metadata)188 static void virgl_get_emulated_metadata(const struct bo *bo, struct bo_metadata *metadata)
189 {
190 uint32_t y_plane_height;
191 uint32_t c_plane_height;
192 uint32_t original_width = bo->meta.width;
193 uint32_t original_height = bo->meta.height;
194
195 metadata->format = DRM_FORMAT_R8;
196 switch (bo->meta.format) {
197 case DRM_FORMAT_NV12:
198 case DRM_FORMAT_NV21:
199 // Bi-planar
200 metadata->num_planes = 2;
201
202 y_plane_height = original_height;
203 c_plane_height = DIV_ROUND_UP(original_height, 2);
204
205 metadata->width = original_width;
206 metadata->height = y_plane_height + c_plane_height;
207
208 // Y-plane (full resolution)
209 metadata->strides[0] = metadata->width;
210 metadata->offsets[0] = 0;
211 metadata->sizes[0] = metadata->width * y_plane_height;
212
213 // CbCr-plane (half resolution, interleaved, placed below Y-plane)
214 metadata->strides[1] = metadata->width;
215 metadata->offsets[1] = metadata->offsets[0] + metadata->sizes[0];
216 metadata->sizes[1] = metadata->width * c_plane_height;
217
218 metadata->total_size = metadata->width * metadata->height;
219 break;
220 case DRM_FORMAT_YVU420:
221 case DRM_FORMAT_YVU420_ANDROID:
222 // Tri-planar
223 metadata->num_planes = 3;
224
225 y_plane_height = original_height;
226 c_plane_height = DIV_ROUND_UP(original_height, 2);
227
228 metadata->width = ALIGN(original_width, 32);
229 metadata->height = y_plane_height + (2 * c_plane_height);
230
231 // Y-plane (full resolution)
232 metadata->strides[0] = metadata->width;
233 metadata->offsets[0] = 0;
234 metadata->sizes[0] = metadata->width * original_height;
235
236 // Cb-plane (half resolution, placed below Y-plane)
237 metadata->strides[1] = metadata->width;
238 metadata->offsets[1] = metadata->offsets[0] + metadata->sizes[0];
239 metadata->sizes[1] = metadata->width * c_plane_height;
240
241 // Cr-plane (half resolution, placed below Cb-plane)
242 metadata->strides[2] = metadata->width;
243 metadata->offsets[2] = metadata->offsets[1] + metadata->sizes[1];
244 metadata->sizes[2] = metadata->width * c_plane_height;
245
246 metadata->total_size = metadata->width * metadata->height;
247 break;
248 default:
249 break;
250 }
251 }
252
253 struct virtio_transfers_params {
254 size_t xfers_needed;
255 struct rectangle xfer_boxes[DRV_MAX_PLANES];
256 };
257
virgl_get_emulated_transfers_params(const struct bo * bo,const struct rectangle * transfer_box,struct virtio_transfers_params * xfer_params)258 static void virgl_get_emulated_transfers_params(const struct bo *bo,
259 const struct rectangle *transfer_box,
260 struct virtio_transfers_params *xfer_params)
261 {
262 uint32_t y_plane_height;
263 uint32_t c_plane_height;
264 struct bo_metadata emulated_metadata = { 0 };
265
266 if (transfer_box->x == 0 && transfer_box->y == 0 && transfer_box->width == bo->meta.width &&
267 transfer_box->height == bo->meta.height) {
268 virgl_get_emulated_metadata(bo, &emulated_metadata);
269
270 xfer_params->xfers_needed = 1;
271 xfer_params->xfer_boxes[0].x = 0;
272 xfer_params->xfer_boxes[0].y = 0;
273 xfer_params->xfer_boxes[0].width = emulated_metadata.width;
274 xfer_params->xfer_boxes[0].height = emulated_metadata.height;
275
276 return;
277 }
278
279 switch (bo->meta.format) {
280 case DRM_FORMAT_NV12:
281 case DRM_FORMAT_NV21:
282 // Bi-planar
283 xfer_params->xfers_needed = 2;
284
285 y_plane_height = bo->meta.height;
286 c_plane_height = DIV_ROUND_UP(bo->meta.height, 2);
287
288 // Y-plane (full resolution)
289 xfer_params->xfer_boxes[0].x = transfer_box->x;
290 xfer_params->xfer_boxes[0].y = transfer_box->y;
291 xfer_params->xfer_boxes[0].width = transfer_box->width;
292 xfer_params->xfer_boxes[0].height = transfer_box->height;
293
294 // CbCr-plane (half resolution, interleaved, placed below Y-plane)
295 xfer_params->xfer_boxes[1].x = transfer_box->x;
296 xfer_params->xfer_boxes[1].y = transfer_box->y + y_plane_height;
297 xfer_params->xfer_boxes[1].width = transfer_box->width;
298 xfer_params->xfer_boxes[1].height = DIV_ROUND_UP(transfer_box->height, 2);
299
300 break;
301 case DRM_FORMAT_YVU420:
302 case DRM_FORMAT_YVU420_ANDROID:
303 // Tri-planar
304 xfer_params->xfers_needed = 3;
305
306 y_plane_height = bo->meta.height;
307 c_plane_height = DIV_ROUND_UP(bo->meta.height, 2);
308
309 // Y-plane (full resolution)
310 xfer_params->xfer_boxes[0].x = transfer_box->x;
311 xfer_params->xfer_boxes[0].y = transfer_box->y;
312 xfer_params->xfer_boxes[0].width = transfer_box->width;
313 xfer_params->xfer_boxes[0].height = transfer_box->height;
314
315 // Cb-plane (half resolution, placed below Y-plane)
316 xfer_params->xfer_boxes[1].x = transfer_box->x;
317 xfer_params->xfer_boxes[1].y = transfer_box->y + y_plane_height;
318 xfer_params->xfer_boxes[1].width = DIV_ROUND_UP(transfer_box->width, 2);
319 xfer_params->xfer_boxes[1].height = DIV_ROUND_UP(transfer_box->height, 2);
320
321 // Cr-plane (half resolution, placed below Cb-plane)
322 xfer_params->xfer_boxes[2].x = transfer_box->x;
323 xfer_params->xfer_boxes[2].y = transfer_box->y + y_plane_height + c_plane_height;
324 xfer_params->xfer_boxes[2].width = DIV_ROUND_UP(transfer_box->width, 2);
325 xfer_params->xfer_boxes[2].height = DIV_ROUND_UP(transfer_box->height, 2);
326
327 break;
328 }
329 }
330
virgl_supports_combination_natively(struct driver * drv,uint32_t drm_format,uint64_t use_flags)331 static bool virgl_supports_combination_natively(struct driver *drv, uint32_t drm_format,
332 uint64_t use_flags)
333 {
334 struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
335
336 if (priv->caps_is_gfxstream) {
337 // If the data is invalid or an older version just accept all formats as previously
338 if (priv->gfxstream_vulkan_caps.protocolVersion == 0 ||
339 priv->gfxstream_vulkan_caps.virglSupportedFormats[0] == 0)
340 return true;
341 bool supported_format = virgl_bitmask_supports_format(
342 (struct virgl_supported_format_mask *)&priv->gfxstream_vulkan_caps
343 .virglSupportedFormats[0],
344 drm_format);
345 return supported_format;
346 }
347 if (priv->caps.max_version == 0)
348 return true;
349
350 if ((use_flags & BO_USE_RENDERING) &&
351 !virgl_bitmask_supports_format(&priv->caps.v1.render, drm_format))
352 return false;
353
354 if ((use_flags & BO_USE_TEXTURE) &&
355 !virgl_bitmask_supports_format(&priv->caps.v1.sampler, drm_format))
356 return false;
357
358 if ((use_flags & BO_USE_SCANOUT) && priv->caps_is_v2 &&
359 !virgl_bitmask_supports_format(&priv->caps.v2.scanout, drm_format))
360 return false;
361
362 return true;
363 }
364
365 // For virtio backends that do not support formats natively (e.g. multi-planar formats are not
366 // supported in virglrenderer when gbm is unavailable on the host machine), whether or not the
367 // format and usage combination can be handled as a blob (byte buffer).
virgl_supports_combination_through_emulation(struct driver * drv,uint32_t drm_format,uint64_t use_flags)368 static bool virgl_supports_combination_through_emulation(struct driver *drv, uint32_t drm_format,
369 uint64_t use_flags)
370 {
371 struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
372
373 // Only enable emulation on non-gbm virtio backends.
374 if (priv->host_gbm_enabled)
375 return false;
376
377 if (use_flags & (BO_USE_RENDERING | BO_USE_SCANOUT))
378 return false;
379
380 if (!virgl_supports_combination_natively(drv, DRM_FORMAT_R8, use_flags))
381 return false;
382
383 return drm_format == DRM_FORMAT_NV12 || drm_format == DRM_FORMAT_NV21 ||
384 drm_format == DRM_FORMAT_YVU420 || drm_format == DRM_FORMAT_YVU420_ANDROID;
385 }
386
387 // Adds the given buffer combination to the list of supported buffer combinations if the
388 // combination is supported by the virtio backend.
virgl_add_combination(struct driver * drv,uint32_t drm_format,struct format_metadata * metadata,uint64_t use_flags)389 static void virgl_add_combination(struct driver *drv, uint32_t drm_format,
390 struct format_metadata *metadata, uint64_t use_flags)
391 {
392 if (params[param_3d].value) {
393 if ((use_flags & BO_USE_SCANOUT) &&
394 !virgl_supports_combination_natively(drv, drm_format, BO_USE_SCANOUT)) {
395 drv_logi("Strip scanout on format: %d\n", drm_format);
396 use_flags &= ~BO_USE_SCANOUT;
397 }
398
399 if (!virgl_supports_combination_natively(drv, drm_format, use_flags) &&
400 !virgl_supports_combination_through_emulation(drv, drm_format, use_flags)) {
401 drv_logi("Skipping unsupported combination format:%d\n", drm_format);
402 return;
403 }
404 }
405
406 drv_add_combination(drv, drm_format, metadata, use_flags);
407 }
408
409 // Adds each given buffer combination to the list of supported buffer combinations if the
410 // combination supported by the virtio backend.
virgl_add_combinations(struct driver * drv,const uint32_t * drm_formats,uint32_t num_formats,struct format_metadata * metadata,uint64_t use_flags)411 static void virgl_add_combinations(struct driver *drv, const uint32_t *drm_formats,
412 uint32_t num_formats, struct format_metadata *metadata,
413 uint64_t use_flags)
414 {
415 uint32_t i;
416
417 for (i = 0; i < num_formats; i++)
418 virgl_add_combination(drv, drm_formats[i], metadata, use_flags);
419 }
420
virgl_2d_dumb_bo_create(struct bo * bo,uint32_t width,uint32_t height,uint32_t format,uint64_t use_flags)421 static int virgl_2d_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
422 uint64_t use_flags)
423 {
424 if (bo->meta.format != DRM_FORMAT_R8) {
425 width = ALIGN(width, MESA_LLVMPIPE_TILE_SIZE);
426 height = ALIGN(height, MESA_LLVMPIPE_TILE_SIZE);
427 }
428
429 return drv_dumb_bo_create_ex(bo, width, height, format, use_flags, BO_QUIRK_DUMB32BPP);
430 }
431
handle_flag(uint64_t * flag,uint64_t check_flag,uint32_t * bind,uint32_t virgl_bind)432 static inline void handle_flag(uint64_t *flag, uint64_t check_flag, uint32_t *bind,
433 uint32_t virgl_bind)
434 {
435 if ((*flag) & check_flag) {
436 (*flag) &= ~check_flag;
437 (*bind) |= virgl_bind;
438 }
439 }
440
compute_virgl_bind_flags(uint64_t use_flags)441 static uint32_t compute_virgl_bind_flags(uint64_t use_flags)
442 {
443 /* In crosvm, VIRGL_BIND_SHARED means minigbm will allocate, not virglrenderer. */
444 uint32_t bind = VIRGL_BIND_SHARED;
445
446 handle_flag(&use_flags, BO_USE_TEXTURE, &bind, VIRGL_BIND_SAMPLER_VIEW);
447 handle_flag(&use_flags, BO_USE_RENDERING, &bind, VIRGL_BIND_RENDER_TARGET);
448 handle_flag(&use_flags, BO_USE_SCANOUT, &bind, VIRGL_BIND_SCANOUT);
449 handle_flag(&use_flags, BO_USE_CURSOR, &bind, VIRGL_BIND_CURSOR);
450 handle_flag(&use_flags, BO_USE_LINEAR, &bind, VIRGL_BIND_LINEAR);
451 handle_flag(&use_flags, BO_USE_SENSOR_DIRECT_DATA, &bind, VIRGL_BIND_LINEAR);
452 handle_flag(&use_flags, BO_USE_GPU_DATA_BUFFER, &bind, VIRGL_BIND_LINEAR);
453 handle_flag(&use_flags, BO_USE_FRONT_RENDERING, &bind, VIRGL_BIND_LINEAR);
454
455 if (use_flags & BO_USE_PROTECTED) {
456 handle_flag(&use_flags, BO_USE_PROTECTED, &bind, VIRGL_BIND_MINIGBM_PROTECTED);
457 } else {
458 // Make sure we don't set both flags, since that could be mistaken for
459 // protected. Give OFTEN priority over RARELY.
460 if (use_flags & BO_USE_SW_READ_OFTEN) {
461 handle_flag(&use_flags, BO_USE_SW_READ_OFTEN, &bind,
462 VIRGL_BIND_MINIGBM_SW_READ_OFTEN);
463 } else {
464 handle_flag(&use_flags, BO_USE_SW_READ_RARELY, &bind,
465 VIRGL_BIND_MINIGBM_SW_READ_RARELY);
466 }
467 if (use_flags & BO_USE_SW_WRITE_OFTEN) {
468 handle_flag(&use_flags, BO_USE_SW_WRITE_OFTEN, &bind,
469 VIRGL_BIND_MINIGBM_SW_WRITE_OFTEN);
470 } else {
471 handle_flag(&use_flags, BO_USE_SW_WRITE_RARELY, &bind,
472 VIRGL_BIND_MINIGBM_SW_WRITE_RARELY);
473 }
474 }
475
476 handle_flag(&use_flags, BO_USE_CAMERA_WRITE, &bind, VIRGL_BIND_MINIGBM_CAMERA_WRITE);
477 handle_flag(&use_flags, BO_USE_CAMERA_READ, &bind, VIRGL_BIND_MINIGBM_CAMERA_READ);
478 handle_flag(&use_flags, BO_USE_HW_VIDEO_DECODER, &bind,
479 VIRGL_BIND_MINIGBM_HW_VIDEO_DECODER);
480 handle_flag(&use_flags, BO_USE_HW_VIDEO_ENCODER, &bind,
481 VIRGL_BIND_MINIGBM_HW_VIDEO_ENCODER);
482
483 if (use_flags)
484 drv_loge("Unhandled bo use flag: %llx\n", (unsigned long long)use_flags);
485
486 return bind;
487 }
488
virgl_3d_bo_create(struct bo * bo,uint32_t width,uint32_t height,uint32_t format,uint64_t use_flags)489 static int virgl_3d_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
490 uint64_t use_flags)
491 {
492 int ret;
493 size_t i;
494 uint32_t stride;
495 struct drm_virtgpu_resource_create res_create = { 0 };
496 struct bo_metadata emulated_metadata = { 0 };
497
498 if (virgl_supports_combination_natively(bo->drv, format, use_flags)) {
499 stride = drv_stride_from_format(format, width, 0);
500 drv_bo_from_format(bo, stride, 1, height, format);
501 } else {
502 assert(virgl_supports_combination_through_emulation(bo->drv, format, use_flags));
503
504 virgl_get_emulated_metadata(bo, &emulated_metadata);
505
506 format = emulated_metadata.format;
507 width = emulated_metadata.width;
508 height = emulated_metadata.height;
509 for (i = 0; i < emulated_metadata.num_planes; i++) {
510 bo->meta.strides[i] = emulated_metadata.strides[i];
511 bo->meta.offsets[i] = emulated_metadata.offsets[i];
512 bo->meta.sizes[i] = emulated_metadata.sizes[i];
513 }
514 bo->meta.total_size = emulated_metadata.total_size;
515 }
516
517 /*
518 * Setting the target is intended to ensure this resource gets bound as a 2D
519 * texture in the host renderer's GL state. All of these resource properties are
520 * sent unchanged by the kernel to the host, which in turn sends them unchanged to
521 * virglrenderer. When virglrenderer makes a resource, it will convert the target
522 * enum to the equivalent one in GL and then bind the resource to that target.
523 */
524
525 res_create.target = PIPE_TEXTURE_2D;
526 res_create.format = translate_format(format);
527 res_create.bind = compute_virgl_bind_flags(use_flags);
528 res_create.width = width;
529 res_create.height = height;
530
531 /* For virgl 3D */
532 res_create.depth = 1;
533 res_create.array_size = 1;
534 res_create.last_level = 0;
535 res_create.nr_samples = 0;
536
537 res_create.size = ALIGN(bo->meta.total_size, PAGE_SIZE); // PAGE_SIZE = 0x1000
538 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE, &res_create);
539 if (ret) {
540 drv_loge("DRM_IOCTL_VIRTGPU_RESOURCE_CREATE failed with %s\n", strerror(errno));
541 return ret;
542 }
543
544 bo->handle.u32 = res_create.bo_handle;
545
546 return 0;
547 }
548
virgl_3d_bo_map(struct bo * bo,struct vma * vma,uint32_t map_flags)549 static void *virgl_3d_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags)
550 {
551 int ret;
552 struct drm_virtgpu_map gem_map = { 0 };
553
554 gem_map.handle = bo->handle.u32;
555 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_MAP, &gem_map);
556 if (ret) {
557 drv_loge("DRM_IOCTL_VIRTGPU_MAP failed with %s\n", strerror(errno));
558 return MAP_FAILED;
559 }
560
561 vma->length = bo->meta.total_size;
562 return mmap(0, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd,
563 gem_map.offset);
564 }
565
virgl_3d_get_max_texture_2d_size(struct driver * drv)566 static uint32_t virgl_3d_get_max_texture_2d_size(struct driver *drv)
567 {
568 struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
569
570 if (priv->caps.v2.max_texture_2d_size)
571 return priv->caps.v2.max_texture_2d_size;
572
573 return UINT32_MAX;
574 }
575
virgl_get_caps(struct driver * drv,struct virgl_priv * priv)576 static int virgl_get_caps(struct driver *drv, struct virgl_priv *priv)
577 {
578 int ret;
579 struct drm_virtgpu_get_caps cap_args = { 0 };
580
581 memset(&priv->caps, 0, sizeof(union virgl_caps));
582 priv->caps_is_v2 = 0;
583 memset(&priv->gfxstream_vulkan_caps, 0, sizeof(struct vulkanCapset));
584
585 if (params[param_supported_capset_ids].value) {
586 drv_logi("Supported CAPSET IDs: %u.", params[param_supported_capset_ids].value);
587 if (params[param_supported_capset_ids].value & (1 << VIRTIO_GPU_CAPSET_VIRGL2)) {
588 priv->caps_is_v2 = 1;
589 } else if (params[param_supported_capset_ids].value &
590 (1 << VIRTIO_GPU_CAPSET_VIRGL)) {
591 priv->caps_is_v2 = 0;
592 } else if (params[param_supported_capset_ids].value &
593 (1 << VIRTIO_GPU_CAPSET_GFXSTREAM_VULKAN)) {
594 priv->caps_is_gfxstream = 1;
595 } else {
596 drv_logi("Unrecognized CAPSET IDs: %u. Assuming all zero caps.",
597 params[param_supported_capset_ids].value);
598 return 0;
599 }
600 } else if (params[param_capset_fix].value) {
601 priv->caps_is_v2 = 1;
602 }
603
604 cap_args.addr = (unsigned long long)&priv->caps;
605 if (priv->caps_is_v2) {
606 cap_args.cap_set_id = VIRTIO_GPU_CAPSET_VIRGL2;
607 cap_args.size = sizeof(union virgl_caps);
608 } else if (priv->caps_is_gfxstream) {
609 cap_args.addr = (unsigned long long)&priv->gfxstream_vulkan_caps;
610 cap_args.cap_set_id = VIRTIO_GPU_CAPSET_GFXSTREAM_VULKAN;
611 cap_args.size = sizeof(struct vulkanCapset);
612 } else {
613 cap_args.cap_set_id = VIRTIO_GPU_CAPSET_VIRGL;
614 cap_args.size = sizeof(struct virgl_caps_v1);
615 }
616
617 ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GET_CAPS, &cap_args);
618 if (ret) {
619 drv_loge("DRM_IOCTL_VIRTGPU_GET_CAPS failed with %s\n", strerror(errno));
620 priv->caps_is_v2 = 0;
621 priv->caps_is_gfxstream = 0;
622 cap_args.addr = (unsigned long long)&priv->caps;
623
624 // Fallback to v1
625 cap_args.cap_set_id = VIRTIO_GPU_CAPSET_VIRGL;
626 cap_args.size = sizeof(struct virgl_caps_v1);
627
628 ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GET_CAPS, &cap_args);
629 if (ret)
630 drv_loge("DRM_IOCTL_VIRTGPU_GET_CAPS failed with %s\n", strerror(errno));
631 }
632
633 return ret;
634 }
635
virgl_init_params_and_caps(struct driver * drv)636 static void virgl_init_params_and_caps(struct driver *drv)
637 {
638 struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
639 if (params[param_3d].value) {
640 virgl_get_caps(drv, priv);
641
642 // We use two criteria to determine whether host minigbm is used on the host for
643 // swapchain allocations.
644 //
645 // (1) Host minigbm is only available via virglrenderer, and only virglrenderer
646 // advertises capabilities.
647 // (2) Only host minigbm doesn't emulate YUV formats. Checking this is a bit of a
648 // proxy, but it works.
649 priv->host_gbm_enabled =
650 priv->caps.max_version > 0 &&
651 virgl_supports_combination_natively(drv, DRM_FORMAT_NV12, BO_USE_TEXTURE);
652 }
653 }
654
virgl_init(struct driver * drv)655 static int virgl_init(struct driver *drv)
656 {
657 struct virgl_priv *priv;
658
659 priv = calloc(1, sizeof(*priv));
660 if (!priv)
661 return -ENOMEM;
662
663 int ret = pthread_mutex_init(&priv->host_blob_format_lock, NULL);
664 if (ret)
665 return ret;
666
667 drv->priv = priv;
668 lru_init(&priv->virgl_blob_metadata_cache, MAX_CACHED_FORMATS);
669
670 virgl_init_params_and_caps(drv);
671
672 if (params[param_3d].value) {
673 /* This doesn't mean host can scanout everything, it just means host
674 * hypervisor can show it. */
675 virgl_add_combinations(drv, render_target_formats,
676 ARRAY_SIZE(render_target_formats), &LINEAR_METADATA,
677 BO_USE_RENDER_MASK | BO_USE_SCANOUT);
678 virgl_add_combinations(drv, texture_source_formats,
679 ARRAY_SIZE(texture_source_formats), &LINEAR_METADATA,
680 BO_USE_TEXTURE_MASK);
681 virgl_add_combinations(drv, depth_stencil_formats,
682 ARRAY_SIZE(depth_stencil_formats), &LINEAR_METADATA,
683 BO_USE_GPU_HW);
684 /* NV12 with scanout must flow through virgl_add_combination, so that the native
685 * support is checked and scanout use_flag can be conditionally stripped. */
686 virgl_add_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA,
687 BO_USE_TEXTURE_MASK | BO_USE_CAMERA_READ |
688 BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER |
689 BO_USE_HW_VIDEO_ENCODER | BO_USE_SCANOUT);
690 } else {
691 /* Virtio primary plane only allows this format. */
692 virgl_add_combination(drv, DRM_FORMAT_XRGB8888, &LINEAR_METADATA,
693 BO_USE_RENDER_MASK | BO_USE_SCANOUT);
694 /* Virtio cursor plane only allows this format and Chrome cannot live without
695 * ARGB888 renderable format. */
696 virgl_add_combination(drv, DRM_FORMAT_ARGB8888, &LINEAR_METADATA,
697 BO_USE_RENDER_MASK | BO_USE_CURSOR);
698 /* Android needs more, but they cannot be bound as scanouts anymore after
699 * "drm/virtio: fix DRM_FORMAT_* handling" */
700 virgl_add_combinations(drv, render_target_formats,
701 ARRAY_SIZE(render_target_formats), &LINEAR_METADATA,
702 BO_USE_RENDER_MASK);
703 virgl_add_combinations(drv, dumb_texture_source_formats,
704 ARRAY_SIZE(dumb_texture_source_formats), &LINEAR_METADATA,
705 BO_USE_TEXTURE_MASK);
706 drv_modify_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA,
707 BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE |
708 BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER);
709 }
710
711 /* Android CTS tests require this. */
712 virgl_add_combination(drv, DRM_FORMAT_RGB888, &LINEAR_METADATA, BO_USE_SW_MASK);
713 virgl_add_combination(drv, DRM_FORMAT_BGR888, &LINEAR_METADATA, BO_USE_SW_MASK);
714 /* Android Camera CTS tests requires this. Additionally, the scanout usage is needed for
715 * Camera preview and is expected to be conditionally stripped by virgl_add_combination
716 * when not natively supported and instead handled by HWComposer. */
717 virgl_add_combination(drv, DRM_FORMAT_P010, &LINEAR_METADATA,
718 BO_USE_SCANOUT | BO_USE_TEXTURE | BO_USE_SW_MASK |
719 BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
720 /* Android VTS sensors hal tests require BO_USE_SENSOR_DIRECT_DATA. */
721 drv_modify_combination(drv, DRM_FORMAT_R8, &LINEAR_METADATA,
722 BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER |
723 BO_USE_HW_VIDEO_ENCODER | BO_USE_SENSOR_DIRECT_DATA |
724 BO_USE_GPU_DATA_BUFFER);
725
726 if (!priv->host_gbm_enabled) {
727 drv_modify_combination(drv, DRM_FORMAT_ABGR8888, &LINEAR_METADATA,
728 BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE |
729 BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER);
730 drv_modify_combination(drv, DRM_FORMAT_XBGR8888, &LINEAR_METADATA,
731 BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE |
732 BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER);
733 drv_modify_combination(drv, DRM_FORMAT_NV21, &LINEAR_METADATA,
734 BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE |
735 BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER);
736 drv_modify_combination(drv, DRM_FORMAT_R16, &LINEAR_METADATA,
737 BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE |
738 BO_USE_HW_VIDEO_DECODER);
739 drv_modify_combination(drv, DRM_FORMAT_YVU420, &LINEAR_METADATA,
740 BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE |
741 BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER);
742 drv_modify_combination(drv, DRM_FORMAT_YVU420_ANDROID, &LINEAR_METADATA,
743 BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE |
744 BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER);
745 }
746
747 return drv_modify_linear_combinations(drv);
748 }
749
virgl_close(struct driver * drv)750 static void virgl_close(struct driver *drv)
751 {
752 free(drv->priv);
753 drv->priv = NULL;
754 }
755
blob_flags_from_use_flags(uint32_t use_flags)756 static uint32_t blob_flags_from_use_flags(uint32_t use_flags)
757 {
758 uint32_t blob_flags = VIRTGPU_BLOB_FLAG_USE_SHAREABLE;
759 if (use_flags & (BO_USE_SW_MASK | BO_USE_GPU_DATA_BUFFER))
760 blob_flags |= VIRTGPU_BLOB_FLAG_USE_MAPPABLE;
761
762 // For now, all blob use cases are cross device. When we add wider
763 // support for blobs, we can revisit making this unconditional.
764 blob_flags |= VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE;
765
766 return blob_flags;
767 }
768
virgl_blob_metadata_eq(struct lru_entry * entry,void * data)769 static bool virgl_blob_metadata_eq(struct lru_entry *entry, void *data)
770 {
771 struct virgl_blob_metadata_cache *e = lru_entry_to_metadata(entry);
772 struct bo_metadata *meta = data;
773 uint32_t virgl_format1 = translate_format(e->meta.format);
774 uint32_t virgl_format2 = translate_format(meta->format);
775
776 return e->meta.height == meta->height && e->meta.width == meta->width &&
777 e->meta.use_flags == meta->use_flags && virgl_format1 == virgl_format2;
778 }
779
virgl_blob_do_create(struct driver * drv,uint32_t width,uint32_t height,uint32_t use_flags,uint32_t virgl_format,uint32_t total_size,uint32_t * bo_handle)780 static int virgl_blob_do_create(struct driver *drv, uint32_t width, uint32_t height,
781 uint32_t use_flags, uint32_t virgl_format, uint32_t total_size,
782 uint32_t *bo_handle)
783 {
784 int ret;
785 uint32_t cur_blob_id;
786 uint32_t cmd[VIRGL_PIPE_RES_CREATE_SIZE + 1] = { 0 };
787 struct drm_virtgpu_resource_create_blob drm_rc_blob = { 0 };
788 struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
789 uint32_t virgl_bind_flags = compute_virgl_bind_flags(use_flags);
790 uint32_t blob_flags = blob_flags_from_use_flags(use_flags);
791
792 cur_blob_id = atomic_fetch_add(&priv->next_blob_id, 1);
793
794 cmd[0] = VIRGL_CMD0(VIRGL_CCMD_PIPE_RESOURCE_CREATE, 0, VIRGL_PIPE_RES_CREATE_SIZE);
795 cmd[VIRGL_PIPE_RES_CREATE_TARGET] = PIPE_TEXTURE_2D;
796 cmd[VIRGL_PIPE_RES_CREATE_WIDTH] = width;
797 cmd[VIRGL_PIPE_RES_CREATE_HEIGHT] = height;
798 cmd[VIRGL_PIPE_RES_CREATE_FORMAT] = virgl_format;
799 cmd[VIRGL_PIPE_RES_CREATE_BIND] = virgl_bind_flags;
800 cmd[VIRGL_PIPE_RES_CREATE_DEPTH] = 1;
801 cmd[VIRGL_PIPE_RES_CREATE_BLOB_ID] = cur_blob_id;
802
803 drm_rc_blob.cmd = (uint64_t)&cmd;
804 drm_rc_blob.cmd_size = 4 * (VIRGL_PIPE_RES_CREATE_SIZE + 1);
805 drm_rc_blob.size = total_size;
806 drm_rc_blob.blob_mem = VIRTGPU_BLOB_MEM_HOST3D;
807 drm_rc_blob.blob_flags = blob_flags;
808 drm_rc_blob.blob_id = cur_blob_id;
809
810 ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB, &drm_rc_blob);
811 if (ret < 0) {
812 drv_loge("DRM_VIRTGPU_RESOURCE_CREATE_BLOB failed with %s\n", strerror(errno));
813 return -errno;
814 }
815
816 *bo_handle = drm_rc_blob.bo_handle;
817 return 0;
818 }
819
820 // Queries the host layout for the requested buffer metadata.
821 //
822 // Of particular interest is total_size. This value is passed to the kernel when creating
823 // a buffer via drm_virtgpu_resource_create_blob.size, to specify how much "vram" to
824 // allocate for use when exposing the host buffer to the guest. As such, we need to know
825 // this value before allocating a buffer to ensure that the full host buffer is actually
826 // visible to the guest.
827 //
828 // Note that we can't reuse these test buffers as actual allocations because our guess for
829 // total_size is insufficient if width!=stride or padding!=0.
virgl_blob_get_host_format(struct driver * drv,struct bo_metadata * meta)830 static int virgl_blob_get_host_format(struct driver *drv, struct bo_metadata *meta)
831 {
832 struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
833 int num_planes = drv_num_planes_from_format(meta->format);
834
835 pthread_mutex_lock(&priv->host_blob_format_lock);
836 if (meta->format == DRM_FORMAT_R8) {
837 meta->offsets[0] = 0;
838 meta->sizes[0] = meta->width;
839 meta->strides[0] = meta->width;
840 meta->total_size = meta->width;
841 } else {
842 uint32_t virgl_format = translate_format(meta->format);
843 struct virgl_blob_metadata_cache *entry;
844
845 entry = lru_entry_to_metadata(
846 lru_find(&priv->virgl_blob_metadata_cache, virgl_blob_metadata_eq, meta));
847
848 if (!entry) {
849 uint32_t total_size = 0;
850 for (int i = 0; i < num_planes; i++) {
851 uint32_t stride =
852 drv_stride_from_format(meta->format, meta->width, i);
853 total_size +=
854 drv_size_from_format(meta->format, stride, meta->height, i);
855 }
856
857 uint32_t handle;
858 int ret =
859 virgl_blob_do_create(drv, meta->width, meta->height, meta->use_flags,
860 virgl_format, total_size, &handle);
861 if (ret) {
862 pthread_mutex_unlock(&priv->host_blob_format_lock);
863 return ret;
864 }
865
866 struct drm_virtgpu_resource_info_cros info = { 0 };
867 info.bo_handle = handle;
868 info.type = VIRTGPU_RESOURCE_INFO_TYPE_EXTENDED;
869 int info_ret =
870 drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_INFO_CROS, &info);
871
872 struct drm_gem_close gem_close = { 0 };
873 gem_close.handle = handle;
874 int close_ret = drmIoctl(drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
875 if (close_ret)
876 drv_loge("DRM_IOCTL_GEM_CLOSE failed (handle=%x) error %d\n",
877 handle, close_ret);
878
879 if (info_ret) {
880 pthread_mutex_unlock(&priv->host_blob_format_lock);
881 drv_loge("Getting resource info failed with %s\n", strerror(errno));
882 return info_ret;
883 }
884
885 entry = calloc(1, sizeof(*entry));
886 entry->meta = *meta;
887
888 for (int i = 0; i < num_planes; i++) {
889 entry->meta.strides[i] = info.strides[i];
890 entry->meta.sizes[i] =
891 info.strides[i] *
892 drv_height_from_format(meta->format, meta->height, i);
893 entry->meta.offsets[i] = info.offsets[i];
894 }
895 entry->meta.total_size =
896 entry->meta.offsets[num_planes - 1] + entry->meta.sizes[num_planes - 1];
897 entry->meta.format_modifier = info.format_modifier;
898
899 lru_insert(&priv->virgl_blob_metadata_cache, &entry->entry);
900 }
901
902 memcpy(meta->offsets, entry->meta.offsets, sizeof(meta->offsets));
903 memcpy(meta->sizes, entry->meta.sizes, sizeof(meta->sizes));
904 memcpy(meta->strides, entry->meta.strides, sizeof(meta->strides));
905 meta->total_size = entry->meta.total_size;
906 meta->format_modifier = entry->meta.format_modifier;
907 }
908 pthread_mutex_unlock(&priv->host_blob_format_lock);
909
910 meta->total_size = ALIGN(meta->total_size, PAGE_SIZE);
911 meta->tiling = blob_flags_from_use_flags(meta->use_flags);
912
913 return 0;
914 }
915
virgl_bo_create_blob(struct driver * drv,struct bo * bo)916 static int virgl_bo_create_blob(struct driver *drv, struct bo *bo)
917 {
918 int ret;
919 uint32_t virgl_format = translate_format(bo->meta.format);
920 uint32_t bo_handle;
921
922 virgl_blob_get_host_format(drv, &bo->meta);
923 ret = virgl_blob_do_create(drv, bo->meta.width, bo->meta.height, bo->meta.use_flags,
924 virgl_format, bo->meta.total_size, &bo_handle);
925 if (ret)
926 return ret;
927
928 bo->handle.u32 = bo_handle;
929
930 return 0;
931 }
932
should_use_blob(struct driver * drv,uint32_t format,uint64_t use_flags)933 static bool should_use_blob(struct driver *drv, uint32_t format, uint64_t use_flags)
934 {
935 struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
936
937 // TODO(gurchetansingh): remove once all minigbm users are blob-safe
938 #ifndef VIRTIO_GPU_NEXT
939 return false;
940 #endif
941
942 // Only use blob when host gbm is available
943 if (!priv->host_gbm_enabled)
944 return false;
945
946 // Use regular resources if only the GPU needs efficient access. Blob resource is a better
947 // fit for BO_USE_GPU_DATA_BUFFER which is mapped to VIRGL_BIND_LINEAR.
948 if (!(use_flags & (BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN | BO_USE_LINEAR |
949 BO_USE_NON_GPU_HW | BO_USE_GPU_DATA_BUFFER)))
950 return false;
951
952 switch (format) {
953 case DRM_FORMAT_R8:
954 // Formats with strictly defined strides are supported
955 return true;
956 case DRM_FORMAT_ABGR8888:
957 // Formats used with frequent software reads are supported as long as they
958 // will not be used by non-GPU hardware.
959 return (use_flags & BO_USE_SW_READ_OFTEN) && !(use_flags & BO_USE_NON_GPU_HW);
960 case DRM_FORMAT_YVU420_ANDROID:
961 case DRM_FORMAT_NV12:
962 // Zero copy buffers are exposed for guest software access via a persistent
963 // mapping, with no flush/invalidate messages. However, the virtio-video
964 // device relies transfers to/from the host waiting on implicit fences in
965 // the host kernel to synchronize with hardware output. As such, we can only
966 // use zero copy if the guest doesn't need software access.
967 return (use_flags & BO_USE_SW_MASK) == 0;
968 default:
969 return false;
970 }
971 }
972
virgl_bo_create(struct bo * bo,uint32_t width,uint32_t height,uint32_t format,uint64_t use_flags)973 static int virgl_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
974 uint64_t use_flags)
975 {
976 if (params[param_resource_blob].value && params[param_host_visible].value &&
977 should_use_blob(bo->drv, format, use_flags))
978 return virgl_bo_create_blob(bo->drv, bo);
979
980 if (params[param_3d].value)
981 return virgl_3d_bo_create(bo, width, height, format, use_flags);
982 else
983 return virgl_2d_dumb_bo_create(bo, width, height, format, use_flags);
984 }
985
virgl_bo_create_with_modifiers(struct bo * bo,uint32_t width,uint32_t height,uint32_t format,const uint64_t * modifiers,uint32_t count)986 static int virgl_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint32_t height,
987 uint32_t format, const uint64_t *modifiers,
988 uint32_t count)
989 {
990 uint64_t use_flags = 0;
991
992 for (uint32_t i = 0; i < count; i++) {
993 if (modifiers[i] == DRM_FORMAT_MOD_LINEAR) {
994 return virgl_bo_create(bo, width, height, format, use_flags);
995 }
996 }
997
998 return -EINVAL;
999 }
1000
virgl_bo_destroy(struct bo * bo)1001 static int virgl_bo_destroy(struct bo *bo)
1002 {
1003 if (params[param_3d].value)
1004 return drv_gem_bo_destroy(bo);
1005 else
1006 return drv_dumb_bo_destroy(bo);
1007 }
1008
virgl_bo_map(struct bo * bo,struct vma * vma,uint32_t map_flags)1009 static void *virgl_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags)
1010 {
1011 if (params[param_3d].value)
1012 return virgl_3d_bo_map(bo, vma, map_flags);
1013 else
1014 return drv_dumb_bo_map(bo, vma, map_flags);
1015 }
1016
is_arc_screen_capture_bo(struct bo * bo)1017 static bool is_arc_screen_capture_bo(struct bo *bo)
1018 {
1019 struct drm_prime_handle prime_handle = {};
1020 int ret, fd;
1021 char tmp[256];
1022
1023 if (bo->meta.num_planes != 1 ||
1024 (bo->meta.format != DRM_FORMAT_ABGR8888 && bo->meta.format != DRM_FORMAT_ARGB8888 &&
1025 bo->meta.format != DRM_FORMAT_XRGB8888 && bo->meta.format != DRM_FORMAT_XBGR8888))
1026 return false;
1027 prime_handle.handle = bo->handle.u32;
1028 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime_handle);
1029 if (ret < 0)
1030 return false;
1031 snprintf(tmp, sizeof(tmp), "/proc/self/fdinfo/%d", prime_handle.fd);
1032 fd = open(tmp, O_RDONLY);
1033 if (fd < 0) {
1034 close(prime_handle.fd);
1035 return false;
1036 }
1037 ret = read(fd, tmp, sizeof(tmp) - 1);
1038 close(prime_handle.fd);
1039 close(fd);
1040 if (ret < 0)
1041 return false;
1042 tmp[ret] = 0;
1043
1044 return strstr(tmp, "ARC-SCREEN-CAP");
1045 }
1046
virgl_bo_invalidate(struct bo * bo,struct mapping * mapping)1047 static int virgl_bo_invalidate(struct bo *bo, struct mapping *mapping)
1048 {
1049 int ret;
1050 size_t i;
1051 struct drm_virtgpu_3d_transfer_from_host xfer = { 0 };
1052 struct drm_virtgpu_3d_wait waitcmd = { 0 };
1053 struct virtio_transfers_params xfer_params;
1054 struct virgl_priv *priv = (struct virgl_priv *)bo->drv->priv;
1055 uint64_t host_write_flags;
1056
1057 if (!params[param_3d].value)
1058 return 0;
1059
1060 // Invalidate is only necessary if the host writes to the buffer. The encoder and
1061 // decoder flags don't differentiate between input and output buffers, but we can
1062 // use the format to determine whether this buffer could be encoder/decoder output.
1063 host_write_flags = BO_USE_RENDERING | BO_USE_CAMERA_WRITE | BO_USE_GPU_DATA_BUFFER;
1064 if (bo->meta.format == DRM_FORMAT_R8)
1065 host_write_flags |= BO_USE_HW_VIDEO_ENCODER;
1066 else
1067 host_write_flags |= BO_USE_HW_VIDEO_DECODER;
1068
1069 // TODO(b/267892346): Revert this workaround after migrating to virtgpu_cross_domain
1070 // backend since it's a special arc only behavior.
1071 if (!(bo->meta.use_flags & (BO_USE_ARC_SCREEN_CAP_PROBED | BO_USE_RENDERING))) {
1072 bo->meta.use_flags |= BO_USE_ARC_SCREEN_CAP_PROBED;
1073 if (is_arc_screen_capture_bo(bo)) {
1074 bo->meta.use_flags |= BO_USE_RENDERING;
1075 }
1076 }
1077
1078 if ((bo->meta.use_flags & host_write_flags) == 0)
1079 return 0;
1080
1081 if (params[param_resource_blob].value && (bo->meta.tiling & VIRTGPU_BLOB_FLAG_USE_MAPPABLE))
1082 return 0;
1083
1084 xfer.bo_handle = mapping->vma->handle;
1085
1086 if (mapping->rect.x || mapping->rect.y) {
1087 /*
1088 * virglrenderer uses the box parameters and assumes that offset == 0 for planar
1089 * images
1090 */
1091 if (bo->meta.num_planes == 1) {
1092 xfer.offset =
1093 (bo->meta.strides[0] * mapping->rect.y) +
1094 drv_bytes_per_pixel_from_format(bo->meta.format, 0) * mapping->rect.x;
1095 }
1096 }
1097
1098 if ((bo->meta.use_flags & BO_USE_RENDERING) == 0) {
1099 // Unfortunately, the kernel doesn't actually pass the guest layer_stride
1100 // and guest stride to the host (compare virgl.h and virtgpu_drm.h).
1101 // For gbm based resources, we can work around this by using the level field
1102 // to pass the stride to virglrenderer's gbm transfer code. However, we need
1103 // to avoid doing this for resources which don't rely on that transfer code,
1104 // which is resources with the BO_USE_RENDERING flag set.
1105 // TODO(b/145993887): Send also stride when the patches are landed
1106 if (priv->host_gbm_enabled)
1107 xfer.level = bo->meta.strides[0];
1108 }
1109
1110 if (virgl_supports_combination_natively(bo->drv, bo->meta.format, bo->meta.use_flags)) {
1111 xfer_params.xfers_needed = 1;
1112 xfer_params.xfer_boxes[0] = mapping->rect;
1113 } else {
1114 assert(virgl_supports_combination_through_emulation(bo->drv, bo->meta.format,
1115 bo->meta.use_flags));
1116
1117 virgl_get_emulated_transfers_params(bo, &mapping->rect, &xfer_params);
1118 }
1119
1120 for (i = 0; i < xfer_params.xfers_needed; i++) {
1121 xfer.box.x = xfer_params.xfer_boxes[i].x;
1122 xfer.box.y = xfer_params.xfer_boxes[i].y;
1123 xfer.box.w = xfer_params.xfer_boxes[i].width;
1124 xfer.box.h = xfer_params.xfer_boxes[i].height;
1125 xfer.box.d = 1;
1126
1127 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST, &xfer);
1128 if (ret) {
1129 drv_loge("DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST failed with %s\n",
1130 strerror(errno));
1131 return -errno;
1132 }
1133 }
1134
1135 // The transfer needs to complete before invalidate returns so that any host changes
1136 // are visible and to ensure the host doesn't overwrite subsequent guest changes.
1137 // TODO(b/136733358): Support returning fences from transfers
1138 waitcmd.handle = mapping->vma->handle;
1139 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_WAIT, &waitcmd);
1140 if (ret) {
1141 drv_loge("DRM_IOCTL_VIRTGPU_WAIT failed with %s\n", strerror(errno));
1142 return -errno;
1143 }
1144
1145 return 0;
1146 }
1147
virgl_bo_flush(struct bo * bo,struct mapping * mapping)1148 static int virgl_bo_flush(struct bo *bo, struct mapping *mapping)
1149 {
1150 int ret;
1151 size_t i;
1152 struct drm_virtgpu_3d_transfer_to_host xfer = { 0 };
1153 struct drm_virtgpu_3d_wait waitcmd = { 0 };
1154 struct virtio_transfers_params xfer_params;
1155 struct virgl_priv *priv = (struct virgl_priv *)bo->drv->priv;
1156
1157 if (!params[param_3d].value)
1158 return 0;
1159
1160 if (!(mapping->vma->map_flags & BO_MAP_WRITE))
1161 return 0;
1162
1163 if (params[param_resource_blob].value && (bo->meta.tiling & VIRTGPU_BLOB_FLAG_USE_MAPPABLE))
1164 return 0;
1165
1166 xfer.bo_handle = mapping->vma->handle;
1167
1168 if (mapping->rect.x || mapping->rect.y) {
1169 /*
1170 * virglrenderer uses the box parameters and assumes that offset == 0 for planar
1171 * images
1172 */
1173 if (bo->meta.num_planes == 1) {
1174 xfer.offset =
1175 (bo->meta.strides[0] * mapping->rect.y) +
1176 drv_bytes_per_pixel_from_format(bo->meta.format, 0) * mapping->rect.x;
1177 }
1178 }
1179
1180 // Unfortunately, the kernel doesn't actually pass the guest layer_stride and
1181 // guest stride to the host (compare virgl.h and virtgpu_drm.h). We can use
1182 // the level to work around this.
1183 if (priv->host_gbm_enabled)
1184 xfer.level = bo->meta.strides[0];
1185
1186 if (virgl_supports_combination_natively(bo->drv, bo->meta.format, bo->meta.use_flags)) {
1187 xfer_params.xfers_needed = 1;
1188 xfer_params.xfer_boxes[0] = mapping->rect;
1189 } else {
1190 assert(virgl_supports_combination_through_emulation(bo->drv, bo->meta.format,
1191 bo->meta.use_flags));
1192
1193 virgl_get_emulated_transfers_params(bo, &mapping->rect, &xfer_params);
1194 }
1195
1196 for (i = 0; i < xfer_params.xfers_needed; i++) {
1197 xfer.box.x = xfer_params.xfer_boxes[i].x;
1198 xfer.box.y = xfer_params.xfer_boxes[i].y;
1199 xfer.box.w = xfer_params.xfer_boxes[i].width;
1200 xfer.box.h = xfer_params.xfer_boxes[i].height;
1201 xfer.box.d = 1;
1202
1203 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST, &xfer);
1204 if (ret) {
1205 drv_loge("DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST failed with %s\n",
1206 strerror(errno));
1207 return -errno;
1208 }
1209 }
1210
1211 // If the buffer is only accessed by the host GPU, then the flush is ordered
1212 // with subsequent commands. However, if other host hardware can access the
1213 // buffer, we need to wait for the transfer to complete for consistency.
1214 // TODO(b/136733358): Support returning fences from transfers
1215 if (bo->meta.use_flags & BO_USE_NON_GPU_HW) {
1216 waitcmd.handle = mapping->vma->handle;
1217
1218 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_WAIT, &waitcmd);
1219 if (ret) {
1220 drv_loge("DRM_IOCTL_VIRTGPU_WAIT failed with %s\n", strerror(errno));
1221 return -errno;
1222 }
1223 }
1224
1225 return 0;
1226 }
1227
virgl_3d_resolve_format_and_use_flags(struct driver * drv,uint32_t format,uint64_t use_flags,uint32_t * out_format,uint64_t * out_use_flags)1228 static void virgl_3d_resolve_format_and_use_flags(struct driver *drv, uint32_t format,
1229 uint64_t use_flags, uint32_t *out_format,
1230 uint64_t *out_use_flags)
1231 {
1232 *out_format = format;
1233 *out_use_flags = use_flags;
1234
1235 /* resolve flexible format into explicit format */
1236 switch (format) {
1237 case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
1238 /* Camera subsystem requires NV12. */
1239 if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE)) {
1240 *out_format = DRM_FORMAT_NV12;
1241 } else {
1242 /* HACK: See b/28671744 and b/264408280 */
1243 *out_format = DRM_FORMAT_XBGR8888;
1244 *out_use_flags &= ~BO_USE_HW_VIDEO_ENCODER;
1245 *out_use_flags |= BO_USE_LINEAR;
1246 }
1247 break;
1248 case DRM_FORMAT_FLEX_YCbCr_420_888:
1249 /* All of our host drivers prefer NV12 as their flexible media format.
1250 * If that changes, this will need to be modified. */
1251 *out_format = DRM_FORMAT_NV12;
1252 break;
1253 default:
1254 break;
1255 }
1256
1257 /* resolve explicit format */
1258 switch (*out_format) {
1259 case DRM_FORMAT_NV12:
1260 case DRM_FORMAT_ABGR8888:
1261 case DRM_FORMAT_ARGB8888:
1262 case DRM_FORMAT_RGB565:
1263 case DRM_FORMAT_XBGR8888:
1264 case DRM_FORMAT_XRGB8888:
1265 /* These are the scanout capable formats to the guest. Strip scanout use_flag if the
1266 * host does not natively support scanout on the requested format. */
1267 if ((*out_use_flags & BO_USE_SCANOUT) &&
1268 !virgl_supports_combination_natively(drv, *out_format, BO_USE_SCANOUT))
1269 *out_use_flags &= ~BO_USE_SCANOUT;
1270 break;
1271 case DRM_FORMAT_YVU420_ANDROID:
1272 *out_use_flags &= ~BO_USE_SCANOUT;
1273 /* HACK: See b/172389166. Also see gbm_bo_create. */
1274 *out_use_flags |= BO_USE_LINEAR;
1275 break;
1276 default:
1277 break;
1278 }
1279 }
1280
virgl_2d_resolve_format_and_use_flags(uint32_t format,uint64_t use_flags,uint32_t * out_format,uint64_t * out_use_flags)1281 static void virgl_2d_resolve_format_and_use_flags(uint32_t format, uint64_t use_flags,
1282 uint32_t *out_format, uint64_t *out_use_flags)
1283 {
1284 *out_format = format;
1285 *out_use_flags = use_flags;
1286
1287 /* HACK: See crrev/c/1849773 */
1288 if (format != DRM_FORMAT_XRGB8888)
1289 *out_use_flags &= ~BO_USE_SCANOUT;
1290
1291 switch (format) {
1292 case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
1293 /* Camera subsystem requires NV12. */
1294 if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE)) {
1295 *out_format = DRM_FORMAT_NV12;
1296 } else {
1297 /* HACK: See b/28671744 */
1298 *out_format = DRM_FORMAT_XBGR8888;
1299 *out_use_flags &= ~BO_USE_HW_VIDEO_ENCODER;
1300 }
1301 break;
1302 case DRM_FORMAT_FLEX_YCbCr_420_888:
1303 *out_format = DRM_FORMAT_YVU420_ANDROID;
1304 /* fallthrough */
1305 case DRM_FORMAT_YVU420_ANDROID:
1306 *out_use_flags &= ~BO_USE_SCANOUT;
1307 /* HACK: See b/172389166. Also see gbm_bo_create. */
1308 *out_use_flags |= BO_USE_LINEAR;
1309 break;
1310 default:
1311 break;
1312 }
1313 }
1314
virgl_resolve_format_and_use_flags(struct driver * drv,uint32_t format,uint64_t use_flags,uint32_t * out_format,uint64_t * out_use_flags)1315 static void virgl_resolve_format_and_use_flags(struct driver *drv, uint32_t format,
1316 uint64_t use_flags, uint32_t *out_format,
1317 uint64_t *out_use_flags)
1318 {
1319 if (params[param_3d].value) {
1320 return virgl_3d_resolve_format_and_use_flags(drv, format, use_flags, out_format,
1321 out_use_flags);
1322 } else {
1323 return virgl_2d_resolve_format_and_use_flags(format, use_flags, out_format,
1324 out_use_flags);
1325 }
1326 }
1327
virgl_resource_info(struct bo * bo,uint32_t strides[DRV_MAX_PLANES],uint32_t offsets[DRV_MAX_PLANES],uint64_t * format_modifier)1328 static int virgl_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES],
1329 uint32_t offsets[DRV_MAX_PLANES], uint64_t *format_modifier)
1330 {
1331 int ret;
1332 struct drm_virtgpu_resource_info_cros res_info = { 0 };
1333
1334 if (!params[param_3d].value)
1335 return 0;
1336
1337 res_info.bo_handle = bo->handle.u32;
1338 res_info.type = VIRTGPU_RESOURCE_INFO_TYPE_EXTENDED;
1339 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_INFO_CROS, &res_info);
1340 if (ret) {
1341 drv_loge("DRM_IOCTL_VIRTGPU_RESOURCE_INFO failed with %s\n", strerror(errno));
1342 return ret;
1343 }
1344
1345 for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++) {
1346 /*
1347 * Currently, kernel v4.14 (Betty) doesn't have the extended resource info
1348 * ioctl.
1349 */
1350 if (!res_info.strides[plane])
1351 break;
1352
1353 strides[plane] = res_info.strides[plane];
1354 offsets[plane] = res_info.offsets[plane];
1355 }
1356 *format_modifier = res_info.format_modifier;
1357
1358 return 0;
1359 }
1360
virgl_get_max_texture_2d_size(struct driver * drv)1361 static uint32_t virgl_get_max_texture_2d_size(struct driver *drv)
1362 {
1363 if (params[param_3d].value)
1364 return virgl_3d_get_max_texture_2d_size(drv);
1365 else
1366 return VIRGL_2D_MAX_TEXTURE_2D_SIZE;
1367 }
1368
1369 const struct backend virtgpu_virgl = { .name = "virtgpu_virgl",
1370 .init = virgl_init,
1371 .close = virgl_close,
1372 .bo_create = virgl_bo_create,
1373 .bo_create_with_modifiers = virgl_bo_create_with_modifiers,
1374 .bo_destroy = virgl_bo_destroy,
1375 .bo_import = drv_prime_bo_import,
1376 .bo_map = virgl_bo_map,
1377 .bo_unmap = drv_bo_munmap,
1378 .bo_invalidate = virgl_bo_invalidate,
1379 .bo_flush = virgl_bo_flush,
1380 .resolve_format_and_use_flags =
1381 virgl_resolve_format_and_use_flags,
1382 .resource_info = virgl_resource_info,
1383 .get_max_texture_2d_size = virgl_get_max_texture_2d_size };
1384