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