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