Snap for 8426163 from 7a1eec2a3310343a52dd0aa09f7c5de2198c20c9 to mainline-tzdata2-release

Change-Id: I7f51b80b9e4780cfb7e0afcea8f265540afa0e4e
diff --git a/Android.bp b/Android.bp
index e7dfff8..02e8e5d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,55 +1,29 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package {
-    default_applicable_licenses: ["external_minigbm_license"],
-}
-
-// Added automatically by a large-scale-change that took the approach of
-// 'apply every license found to every target'. While this makes sure we respect
-// every license restriction, it may not be entirely correct.
-//
-// e.g. GPL in an MIT project might only apply to the contrib/ directory.
-//
-// Please consider splitting the single license below into multiple licenses,
-// taking care not to lose any license_kind information, and overriding the
-// default license using the 'licenses: [...]' property on targets as needed.
-//
-// For unused files, consider creating a 'fileGroup' with "//visibility:private"
-// to attach the license to, and including a comment whether the files may be
-// used in the current project.
-// See: http://go/android-license-faq
-license {
-    name: "external_minigbm_license",
-    visibility: [":__subpackages__"],
-    license_kinds: [
-        "SPDX-license-identifier-Apache-2.0",
-        "SPDX-license-identifier-BSD",
-        "SPDX-license-identifier-MIT",
-    ],
-    license_text: [
-        "LICENSE",
-    ],
-}
-
 cc_defaults {
     name: "minigbm_defaults",
 
     srcs: [
         "amdgpu.c",
         "drv.c",
-        "dumb_driver.c",
+        "evdi.c",
         "exynos.c",
         "helpers_array.c",
         "helpers.c",
         "i915.c",
+        "marvell.c",
         "mediatek.c",
+        "meson.c",
         "msm.c",
+        "nouveau.c",
+        "radeon.c",
         "rockchip.c",
+        "tegra.c",
+        "udl.c",
         "vc4.c",
-        "virtgpu.c",
-        "virtgpu_cross_domain.c",
-        "virtgpu_virgl.c",
+        "vgem.c",
+        "virtio_gpu.c",
     ],
 
     cflags: [
@@ -62,14 +36,9 @@
         "-Wcast-align",
         "-Wno-unused-parameter",
     ],
-
     cppflags: ["-std=c++14"],
-}
 
-cc_defaults {
-    name: "minigbm_cros_gralloc_defaults",
-
-    defaults: ["minigbm_defaults"],
+    vendor: true,
 
     header_libs: [
         "libhardware_headers",
@@ -85,18 +54,6 @@
         "libsystem_headers",
     ],
 
-    srcs: [
-        "cros_gralloc/cros_gralloc_buffer.cc",
-        "cros_gralloc/cros_gralloc_helpers.cc",
-        "cros_gralloc/cros_gralloc_driver.cc",
-    ],
-
-    static_libs: ["libarect"],
-
-    export_static_lib_headers: ["libarect"],
-
-    vendor: true,
-
     shared_libs: [
         "libcutils",
         "libdrm",
@@ -105,15 +62,30 @@
         "liblog",
     ],
 
-    relative_install_path: "hw",
+    static_libs: ["libarect"],
+
+    export_static_lib_headers: ["libarect"],
 }
 
 cc_defaults {
-    name: "gbm_defaults",
+    name: "minigbm_cros_gralloc_defaults",
 
     defaults: ["minigbm_defaults"],
 
     srcs: [
+        "cros_gralloc/cros_gralloc_buffer.cc",
+        "cros_gralloc/cros_gralloc_helpers.cc",
+        "cros_gralloc/cros_gralloc_driver.cc",
+    ]
+}
+
+cc_library_static {
+    name: "libminigbm",
+    defaults: ["minigbm_defaults"],
+    shared_libs: ["liblog"],
+    static_libs: ["libdrm"],
+
+    srcs: [
         "gbm.c",
         "gbm_helpers.c",
     ],
@@ -121,34 +93,8 @@
     export_include_dirs: ["."],
 }
 
-cc_library {
-    name: "libgbm",
-    defaults: ["gbm_defaults"],
-    host_supported: true,
-
-    target: {
-        host: {
-            // Avoid linking to another host copy of libdrm; this library will cause
-            // binary GPU drivers to be loaded from the host, which might be linked
-            // to a system copy of libdrm, which conflicts with the AOSP one
-            allow_undefined_symbols: true,
-            header_libs: ["libdrm_headers"],
-        },
-        android: {
-            shared_libs: [
-                "libdrm",
-                "liblog"
-            ],
-        },
-    },
-    apex_available: [
-        "//apex_available:platform",
-        "com.android.virt",
-    ],
-}
-
-cc_defaults {
-    name: "libminigbm_cros_gralloc_defaults",
+cc_library_static {
+    name: "libminigbm_cros_gralloc",
     defaults: ["minigbm_cros_gralloc_defaults"],
     shared_libs: ["liblog"],
     static_libs: ["libdrm"],
@@ -156,11 +102,6 @@
     export_include_dirs: ["."],
 }
 
-cc_library_static {
-    name: "libminigbm_cros_gralloc",
-    defaults: ["libminigbm_cros_gralloc_defaults"],
-}
-
 cc_library_shared {
     name: "gralloc.minigbm",
     defaults: ["minigbm_cros_gralloc_defaults"],
@@ -188,19 +129,4 @@
     defaults: ["minigbm_cros_gralloc_defaults"],
     cflags: ["-DDRV_MESON"],
     srcs: ["cros_gralloc/gralloc0/gralloc0.cc"],
-}
-
-cc_library_shared {
-    name: "gralloc.minigbm_msm",
-    defaults: ["minigbm_cros_gralloc_defaults"],
-    cflags: ["-DDRV_MSM"],
-    srcs: [
-        "cros_gralloc/gralloc0/gralloc0.cc",
-    ],
-}
-
-cc_library_static {
-    name: "libminigbm_cros_gralloc_msm",
-    defaults: ["libminigbm_cros_gralloc_defaults"],
-    cflags: ["-DDRV_MSM"],
-}
+}
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 8238026..35f92f2 100644
--- a/Makefile
+++ b/Makefile
@@ -25,9 +25,6 @@
 ifdef DRV_MESON
 	CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_meson)
 endif
-ifdef DRV_MSM
-	CFLAGS += -ldl
-endif
 ifdef DRV_RADEON
 	CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_radeon)
 endif
diff --git a/OWNERS b/OWNERS
index 6a69a37..d9d5bf3 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,10 +1,11 @@
+dbehr@chromium.org
+dcastagna@chromium.org
+ddavenport@chromium.org
 gurchetansingh@chromium.org
 hoegsberg@chromium.org
+ihf@chromium.org
+lepton@chromium.org
 marcheu@chromium.org
 stevensd@chromium.org
 tfiga@chromium.org
-
-# Also natsu@google.com is great for gralloc/Android stuff but doesn't have a
-# chromium account.
-# So any team members can +2
-*
+tutankhamen@chromium.org
diff --git a/amdgpu.c b/amdgpu.c
index f987f6f..795d137 100644
--- a/amdgpu.c
+++ b/amdgpu.c
@@ -26,284 +26,18 @@
 /* DRI backend decides tiling in this case. */
 #define TILE_TYPE_DRI 1
 
-/* Height alignement for Encoder/Decoder buffers */
-#define CHROME_HEIGHT_ALIGN 16
-
 struct amdgpu_priv {
 	struct dri_driver dri;
 	int drm_version;
-
-	/* sdma */
-	struct drm_amdgpu_info_device dev_info;
-	uint32_t sdma_ctx;
-	uint32_t sdma_cmdbuf_bo;
-	uint64_t sdma_cmdbuf_addr;
-	uint64_t sdma_cmdbuf_size;
-	uint32_t *sdma_cmdbuf_map;
 };
 
-struct amdgpu_linear_vma_priv {
-	uint32_t handle;
-	uint32_t map_flags;
-};
+const static uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888,
+						  DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888,
+						  DRM_FORMAT_XRGB8888 };
 
-const static uint32_t render_target_formats[] = {
-	DRM_FORMAT_ABGR8888,	  DRM_FORMAT_ARGB8888,	  DRM_FORMAT_RGB565,
-	DRM_FORMAT_XBGR8888,	  DRM_FORMAT_XRGB8888,	  DRM_FORMAT_ABGR2101010,
-	DRM_FORMAT_ARGB2101010,	  DRM_FORMAT_XBGR2101010, DRM_FORMAT_XRGB2101010,
-	DRM_FORMAT_ABGR16161616F,
-};
-
-const static uint32_t texture_source_formats[] = {
-	DRM_FORMAT_GR88,	   DRM_FORMAT_R8,     DRM_FORMAT_NV21, DRM_FORMAT_NV12,
-	DRM_FORMAT_YVU420_ANDROID, DRM_FORMAT_YVU420, DRM_FORMAT_P010
-};
-
-static int query_dev_info(int fd, struct drm_amdgpu_info_device *dev_info)
-{
-	struct drm_amdgpu_info info_args = { 0 };
-
-	info_args.return_pointer = (uintptr_t)dev_info;
-	info_args.return_size = sizeof(*dev_info);
-	info_args.query = AMDGPU_INFO_DEV_INFO;
-
-	return drmCommandWrite(fd, DRM_AMDGPU_INFO, &info_args, sizeof(info_args));
-}
-
-static int sdma_init(struct amdgpu_priv *priv, int fd)
-{
-	union drm_amdgpu_ctx ctx_args = { { 0 } };
-	union drm_amdgpu_gem_create gem_create = { { 0 } };
-	struct drm_amdgpu_gem_va va_args = { 0 };
-	union drm_amdgpu_gem_mmap gem_map = { { 0 } };
-	struct drm_gem_close gem_close = { 0 };
-	int ret;
-
-	/* Ensure we can make a submission without BO lists. */
-	if (priv->drm_version < 27)
-		return 0;
-
-	/* Anything outside this range needs adjustments to the SDMA copy commands */
-	if (priv->dev_info.family < AMDGPU_FAMILY_CI || priv->dev_info.family > AMDGPU_FAMILY_NV)
-		return 0;
-
-	ctx_args.in.op = AMDGPU_CTX_OP_ALLOC_CTX;
-
-	ret = drmCommandWriteRead(fd, DRM_AMDGPU_CTX, &ctx_args, sizeof(ctx_args));
-	if (ret < 0)
-		return ret;
-
-	priv->sdma_ctx = ctx_args.out.alloc.ctx_id;
-
-	priv->sdma_cmdbuf_size = ALIGN(4096, priv->dev_info.virtual_address_alignment);
-	gem_create.in.bo_size = priv->sdma_cmdbuf_size;
-	gem_create.in.alignment = 4096;
-	gem_create.in.domains = AMDGPU_GEM_DOMAIN_GTT;
-
-	ret = drmCommandWriteRead(fd, DRM_AMDGPU_GEM_CREATE, &gem_create, sizeof(gem_create));
-	if (ret < 0)
-		goto fail_ctx;
-
-	priv->sdma_cmdbuf_bo = gem_create.out.handle;
-
-	priv->sdma_cmdbuf_addr =
-	    ALIGN(priv->dev_info.virtual_address_offset, priv->dev_info.virtual_address_alignment);
-
-	/* Map the buffer into the GPU address space so we can use it from the GPU */
-	va_args.handle = priv->sdma_cmdbuf_bo;
-	va_args.operation = AMDGPU_VA_OP_MAP;
-	va_args.flags = AMDGPU_VM_PAGE_READABLE | AMDGPU_VM_PAGE_EXECUTABLE;
-	va_args.va_address = priv->sdma_cmdbuf_addr;
-	va_args.offset_in_bo = 0;
-	va_args.map_size = priv->sdma_cmdbuf_size;
-
-	ret = drmCommandWrite(fd, DRM_AMDGPU_GEM_VA, &va_args, sizeof(va_args));
-	if (ret)
-		goto fail_bo;
-
-	gem_map.in.handle = priv->sdma_cmdbuf_bo;
-	ret = drmIoctl(fd, DRM_IOCTL_AMDGPU_GEM_MMAP, &gem_map);
-	if (ret)
-		goto fail_va;
-
-	priv->sdma_cmdbuf_map = mmap(0, priv->sdma_cmdbuf_size, PROT_READ | PROT_WRITE, MAP_SHARED,
-				     fd, gem_map.out.addr_ptr);
-	if (priv->sdma_cmdbuf_map == MAP_FAILED) {
-		priv->sdma_cmdbuf_map = NULL;
-		ret = -ENOMEM;
-		goto fail_va;
-	}
-
-	return 0;
-fail_va:
-	va_args.operation = AMDGPU_VA_OP_UNMAP;
-	va_args.flags = 0;
-	drmCommandWrite(fd, DRM_AMDGPU_GEM_VA, &va_args, sizeof(va_args));
-fail_bo:
-	gem_close.handle = priv->sdma_cmdbuf_bo;
-	drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
-fail_ctx:
-	memset(&ctx_args, 0, sizeof(ctx_args));
-	ctx_args.in.op = AMDGPU_CTX_OP_FREE_CTX;
-	ctx_args.in.ctx_id = priv->sdma_ctx;
-	drmCommandWriteRead(fd, DRM_AMDGPU_CTX, &ctx_args, sizeof(ctx_args));
-	return ret;
-}
-
-static void sdma_finish(struct amdgpu_priv *priv, int fd)
-{
-	union drm_amdgpu_ctx ctx_args = { { 0 } };
-	struct drm_amdgpu_gem_va va_args = { 0 };
-	struct drm_gem_close gem_close = { 0 };
-
-	if (!priv->sdma_cmdbuf_map)
-		return;
-
-	va_args.handle = priv->sdma_cmdbuf_bo;
-	va_args.operation = AMDGPU_VA_OP_UNMAP;
-	va_args.flags = 0;
-	va_args.va_address = priv->sdma_cmdbuf_addr;
-	va_args.offset_in_bo = 0;
-	va_args.map_size = priv->sdma_cmdbuf_size;
-	drmCommandWrite(fd, DRM_AMDGPU_GEM_VA, &va_args, sizeof(va_args));
-
-	gem_close.handle = priv->sdma_cmdbuf_bo;
-	drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
-
-	ctx_args.in.op = AMDGPU_CTX_OP_FREE_CTX;
-	ctx_args.in.ctx_id = priv->sdma_ctx;
-	drmCommandWriteRead(fd, DRM_AMDGPU_CTX, &ctx_args, sizeof(ctx_args));
-}
-
-static int sdma_copy(struct amdgpu_priv *priv, int fd, uint32_t src_handle, uint32_t dst_handle,
-		     uint64_t size)
-{
-	const uint64_t max_size_per_cmd = 0x3fff00;
-	const uint32_t cmd_size = 7 * sizeof(uint32_t); /* 7 dwords, see loop below. */
-	const uint64_t max_commands = priv->sdma_cmdbuf_size / cmd_size;
-	uint64_t src_addr = priv->sdma_cmdbuf_addr + priv->sdma_cmdbuf_size;
-	uint64_t dst_addr = src_addr + size;
-	struct drm_amdgpu_gem_va va_args = { 0 };
-	unsigned cmd = 0;
-	uint64_t remaining_size = size;
-	uint64_t cur_src_addr = src_addr;
-	uint64_t cur_dst_addr = dst_addr;
-	struct drm_amdgpu_cs_chunk_ib ib = { 0 };
-	struct drm_amdgpu_cs_chunk chunks[2] = { { 0 } };
-	uint64_t chunk_ptrs[2];
-	union drm_amdgpu_cs cs = { { 0 } };
-	struct drm_amdgpu_bo_list_in bo_list = { 0 };
-	struct drm_amdgpu_bo_list_entry bo_list_entries[3] = { { 0 } };
-	union drm_amdgpu_wait_cs wait_cs = { { 0 } };
-	int ret = 0;
-
-	if (size > UINT64_MAX - max_size_per_cmd ||
-	    DIV_ROUND_UP(size, max_size_per_cmd) > max_commands)
-		return -ENOMEM;
-
-	/* Map both buffers into the GPU address space so we can access them from the GPU. */
-	va_args.handle = src_handle;
-	va_args.operation = AMDGPU_VA_OP_MAP;
-	va_args.flags = AMDGPU_VM_PAGE_READABLE | AMDGPU_VM_DELAY_UPDATE;
-	va_args.va_address = src_addr;
-	va_args.map_size = size;
-
-	ret = drmCommandWrite(fd, DRM_AMDGPU_GEM_VA, &va_args, sizeof(va_args));
-	if (ret)
-		return ret;
-
-	va_args.handle = dst_handle;
-	va_args.flags = AMDGPU_VM_PAGE_READABLE | AMDGPU_VM_PAGE_WRITEABLE | AMDGPU_VM_DELAY_UPDATE;
-	va_args.va_address = dst_addr;
-
-	ret = drmCommandWrite(fd, DRM_AMDGPU_GEM_VA, &va_args, sizeof(va_args));
-	if (ret)
-		goto unmap_src;
-
-	while (remaining_size) {
-		uint64_t cur_size = remaining_size;
-		if (cur_size > max_size_per_cmd)
-			cur_size = max_size_per_cmd;
-
-		priv->sdma_cmdbuf_map[cmd++] = 0x01; /* linear copy */
-		priv->sdma_cmdbuf_map[cmd++] =
-		    priv->dev_info.family >= AMDGPU_FAMILY_AI ? (cur_size - 1) : cur_size;
-		priv->sdma_cmdbuf_map[cmd++] = 0;
-		priv->sdma_cmdbuf_map[cmd++] = cur_src_addr;
-		priv->sdma_cmdbuf_map[cmd++] = cur_src_addr >> 32;
-		priv->sdma_cmdbuf_map[cmd++] = cur_dst_addr;
-		priv->sdma_cmdbuf_map[cmd++] = cur_dst_addr >> 32;
-
-		remaining_size -= cur_size;
-		cur_src_addr += cur_size;
-		cur_dst_addr += cur_size;
-	}
-
-	ib.va_start = priv->sdma_cmdbuf_addr;
-	ib.ib_bytes = cmd * 4;
-	ib.ip_type = AMDGPU_HW_IP_DMA;
-
-	chunks[1].chunk_id = AMDGPU_CHUNK_ID_IB;
-	chunks[1].length_dw = sizeof(ib) / 4;
-	chunks[1].chunk_data = (uintptr_t)&ib;
-
-	bo_list_entries[0].bo_handle = priv->sdma_cmdbuf_bo;
-	bo_list_entries[0].bo_priority = 8; /* Middle of range, like RADV. */
-	bo_list_entries[1].bo_handle = src_handle;
-	bo_list_entries[1].bo_priority = 8;
-	bo_list_entries[2].bo_handle = dst_handle;
-	bo_list_entries[2].bo_priority = 8;
-
-	bo_list.bo_number = 3;
-	bo_list.bo_info_size = sizeof(bo_list_entries[0]);
-	bo_list.bo_info_ptr = (uintptr_t)bo_list_entries;
-
-	chunks[0].chunk_id = AMDGPU_CHUNK_ID_BO_HANDLES;
-	chunks[0].length_dw = sizeof(bo_list) / 4;
-	chunks[0].chunk_data = (uintptr_t)&bo_list;
-
-	chunk_ptrs[0] = (uintptr_t)&chunks[0];
-	chunk_ptrs[1] = (uintptr_t)&chunks[1];
-
-	cs.in.ctx_id = priv->sdma_ctx;
-	cs.in.num_chunks = 2;
-	cs.in.chunks = (uintptr_t)chunk_ptrs;
-
-	ret = drmCommandWriteRead(fd, DRM_AMDGPU_CS, &cs, sizeof(cs));
-	if (ret) {
-		drv_log("SDMA copy command buffer submission failed %d\n", ret);
-		goto unmap_dst;
-	}
-
-	wait_cs.in.handle = cs.out.handle;
-	wait_cs.in.ip_type = AMDGPU_HW_IP_DMA;
-	wait_cs.in.ctx_id = priv->sdma_ctx;
-	wait_cs.in.timeout = INT64_MAX;
-
-	ret = drmCommandWriteRead(fd, DRM_AMDGPU_WAIT_CS, &wait_cs, sizeof(wait_cs));
-	if (ret) {
-		drv_log("Could not wait for CS to finish\n");
-	} else if (wait_cs.out.status) {
-		drv_log("Infinite wait timed out, likely GPU hang.\n");
-		ret = -ENODEV;
-	}
-
-unmap_dst:
-	va_args.handle = dst_handle;
-	va_args.operation = AMDGPU_VA_OP_UNMAP;
-	va_args.flags = AMDGPU_VM_DELAY_UPDATE;
-	va_args.va_address = dst_addr;
-	drmCommandWrite(fd, DRM_AMDGPU_GEM_VA, &va_args, sizeof(va_args));
-
-unmap_src:
-	va_args.handle = src_handle;
-	va_args.operation = AMDGPU_VA_OP_UNMAP;
-	va_args.flags = AMDGPU_VM_DELAY_UPDATE;
-	va_args.va_address = src_addr;
-	drmCommandWrite(fd, DRM_AMDGPU_GEM_VA, &va_args, sizeof(va_args));
-
-	return ret;
-}
+const static uint32_t texture_source_formats[] = { DRM_FORMAT_GR88,	      DRM_FORMAT_R8,
+						   DRM_FORMAT_NV21,	      DRM_FORMAT_NV12,
+						   DRM_FORMAT_YVU420_ANDROID, DRM_FORMAT_YVU420 };
 
 static int amdgpu_init(struct driver *drv)
 {
@@ -327,21 +61,12 @@
 
 	drv->priv = priv;
 
-	if (query_dev_info(drv_get_fd(drv), &priv->dev_info)) {
-		free(priv);
-		drv->priv = NULL;
-		return -ENODEV;
-	}
 	if (dri_init(drv, DRI_PATH, "radeonsi")) {
 		free(priv);
 		drv->priv = NULL;
 		return -ENODEV;
 	}
 
-	/* Continue on failure, as we can still succesfully map things without SDMA. */
-	if (sdma_init(priv, drv_get_fd(drv)))
-		drv_log("SDMA init failed\n");
-
 	metadata.tiling = TILE_TYPE_LINEAR;
 	metadata.priority = 1;
 	metadata.modifier = DRM_FORMAT_MOD_LINEAR;
@@ -352,15 +77,12 @@
 	drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats),
 			     &metadata, BO_USE_TEXTURE_MASK);
 
-	/* NV12 format for camera, display, decoding and encoding. */
-	drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata,
-			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_SCANOUT |
-				   BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER |
-				   BO_USE_PROTECTED);
-
-	drv_modify_combination(drv, DRM_FORMAT_P010, &metadata,
-			       BO_USE_SCANOUT | BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER |
-				   BO_USE_PROTECTED);
+	/*
+	 * Chrome uses DMA-buf mmap to write to YV12 buffers, which are then accessed by the
+	 * Video Encoder Accelerator (VEA). It could also support NV12 potentially in the future.
+	 */
+	drv_modify_combination(drv, DRM_FORMAT_YVU420, &metadata, BO_USE_HW_VIDEO_ENCODER);
+	drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata, BO_USE_HW_VIDEO_ENCODER);
 
 	/* Android CTS tests require this. */
 	drv_add_combination(drv, DRM_FORMAT_BGR888, &metadata, BO_USE_SW_MASK);
@@ -371,20 +93,19 @@
 	drv_modify_combination(drv, DRM_FORMAT_ABGR8888, &metadata, BO_USE_SCANOUT);
 	drv_modify_combination(drv, DRM_FORMAT_XBGR8888, &metadata, BO_USE_SCANOUT);
 
-	drv_modify_combination(drv, DRM_FORMAT_ABGR2101010, &metadata, BO_USE_SCANOUT);
-	drv_modify_combination(drv, DRM_FORMAT_ARGB2101010, &metadata, BO_USE_SCANOUT);
-	drv_modify_combination(drv, DRM_FORMAT_XBGR2101010, &metadata, BO_USE_SCANOUT);
-	drv_modify_combination(drv, DRM_FORMAT_XRGB2101010, &metadata, BO_USE_SCANOUT);
+	/* YUV formats for camera and display. */
+	drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata,
+			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_SCANOUT |
+				   BO_USE_HW_VIDEO_DECODER);
 
 	drv_modify_combination(drv, DRM_FORMAT_NV21, &metadata, BO_USE_SCANOUT);
 
 	/*
 	 * R8 format is used for Android's HAL_PIXEL_FORMAT_BLOB and is used for JPEG snapshots
-	 * from camera and input/output from hardware decoder/encoder.
+	 * from camera.
 	 */
 	drv_modify_combination(drv, DRM_FORMAT_R8, &metadata,
-			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER |
-				   BO_USE_HW_VIDEO_ENCODER);
+			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
 
 	/*
 	 * The following formats will be allocated by the DRI backend and may be potentially tiled.
@@ -407,17 +128,11 @@
 	drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT);
 	drv_modify_combination(drv, DRM_FORMAT_ABGR8888, &metadata, BO_USE_SCANOUT);
 	drv_modify_combination(drv, DRM_FORMAT_XBGR8888, &metadata, BO_USE_SCANOUT);
-
-	drv_modify_combination(drv, DRM_FORMAT_ABGR2101010, &metadata, BO_USE_SCANOUT);
-	drv_modify_combination(drv, DRM_FORMAT_ARGB2101010, &metadata, BO_USE_SCANOUT);
-	drv_modify_combination(drv, DRM_FORMAT_XBGR2101010, &metadata, BO_USE_SCANOUT);
-	drv_modify_combination(drv, DRM_FORMAT_XRGB2101010, &metadata, BO_USE_SCANOUT);
 	return 0;
 }
 
 static void amdgpu_close(struct driver *drv)
 {
-	sdma_finish(drv->priv, drv_get_fd(drv));
 	dri_close(drv);
 	free(drv->priv);
 	drv->priv = NULL;
@@ -427,39 +142,16 @@
 				   uint64_t use_flags)
 {
 	int ret;
-	size_t num_planes;
 	uint32_t plane, stride;
-	union drm_amdgpu_gem_create gem_create = { { 0 } };
-	struct amdgpu_priv *priv = bo->drv->priv;
+	union drm_amdgpu_gem_create gem_create;
 
 	stride = drv_stride_from_format(format, width, 0);
-	num_planes = drv_num_planes_from_format(format);
-
-	/*
-	 * For multiplane formats, align the stride to 512 to ensure that subsample strides are 256
-	 * aligned. This uses more memory than necessary since the first plane only needs to be
-	 * 256 aligned, but it's acceptable for a short-term fix. It's probably safe for other gpu
-	 * families, but let's restrict it to Raven for now (b/171013552).
-	 * */
-	if (priv->dev_info.family == AMDGPU_FAMILY_RV && num_planes > 1)
-		stride = ALIGN(stride, 512);
-	else
-		stride = ALIGN(stride, 256);
-
-	/*
-	 * Currently, allocator used by chrome aligns the height for Encoder/
-	 * Decoder buffers while allocator used by android(gralloc/minigbm)
-	 * doesn't provide any aligment.
-	 *
-	 * See b/153130069
-	 */
-	if (use_flags & (BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER))
-		height = ALIGN(height, CHROME_HEIGHT_ALIGN);
+	stride = ALIGN(stride, 256);
 
 	drv_bo_from_format(bo, stride, height, format);
 
-	gem_create.in.bo_size =
-	    ALIGN(bo->meta.total_size, priv->dev_info.virtual_address_alignment);
+	memset(&gem_create, 0, sizeof(gem_create));
+	gem_create.in.bo_size = bo->meta.total_size;
 	gem_create.in.alignment = 256;
 	gem_create.in.domain_flags = 0;
 
@@ -467,17 +159,9 @@
 		gem_create.in.domain_flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
 
 	gem_create.in.domains = AMDGPU_GEM_DOMAIN_GTT;
-
-	/* Scanout in GTT requires USWC, otherwise try to use cachable memory
-	 * for buffers that are read often, because uncacheable reads can be
-	 * very slow. USWC should be faster on the GPU though. */
-	if ((use_flags & BO_USE_SCANOUT) || !(use_flags & BO_USE_SW_READ_OFTEN))
+	if (!(use_flags & (BO_USE_SW_READ_OFTEN | BO_USE_SCANOUT)))
 		gem_create.in.domain_flags |= AMDGPU_GEM_CREATE_CPU_GTT_USWC;
 
-	/* For protected data Buffer needs to be allocated from TMZ */
-	if (use_flags & BO_USE_PROTECTED)
-		gem_create.in.domain_flags |= AMDGPU_GEM_CREATE_ENCRYPTED;
-
 	/* Allocate the buffer with the preferred heap. */
 	ret = drmCommandWriteRead(drv_get_fd(bo->drv), DRM_AMDGPU_GEM_CREATE, &gem_create,
 				  sizeof(gem_create));
@@ -487,7 +171,7 @@
 	for (plane = 0; plane < bo->meta.num_planes; plane++)
 		bo->handles[plane].u32 = gem_create.out.handle;
 
-	bo->meta.format_modifier = DRM_FORMAT_MOD_LINEAR;
+	bo->meta.format_modifiers[0] = DRM_FORMAT_MOD_LINEAR;
 
 	return 0;
 }
@@ -496,7 +180,6 @@
 			    uint64_t use_flags)
 {
 	struct combination *combo;
-	struct amdgpu_priv *priv = bo->drv->priv;
 
 	combo = drv_get_combination(bo->drv, format, use_flags);
 	if (!combo)
@@ -516,7 +199,7 @@
 			needs_alignment = true;
 #endif
 		// See b/122049612
-		if (use_flags & (BO_USE_SCANOUT) && priv->dev_info.family == AMDGPU_FAMILY_CZ)
+		if (use_flags & (BO_USE_SCANOUT))
 			needs_alignment = true;
 
 		if (needs_alignment) {
@@ -548,8 +231,8 @@
 
 static int amdgpu_import_bo(struct bo *bo, struct drv_import_fd_data *data)
 {
-	bool dri_tiling = data->format_modifier != DRM_FORMAT_MOD_LINEAR;
-	if (data->format_modifier == DRM_FORMAT_MOD_INVALID) {
+	bool dri_tiling = data->format_modifiers[0] != DRM_FORMAT_MOD_LINEAR;
+	if (data->format_modifiers[0] == DRM_FORMAT_MOD_INVALID) {
 		struct combination *combo;
 		combo = drv_get_combination(bo->drv, data->format, data->use_flags);
 		if (!combo)
@@ -574,122 +257,44 @@
 
 static void *amdgpu_map_bo(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
 {
-	void *addr = MAP_FAILED;
 	int ret;
-	union drm_amdgpu_gem_mmap gem_map = { { 0 } };
-	struct drm_amdgpu_gem_create_in bo_info = { 0 };
-	struct drm_amdgpu_gem_op gem_op = { 0 };
-	uint32_t handle = bo->handles[plane].u32;
-	struct amdgpu_linear_vma_priv *priv = NULL;
-	struct amdgpu_priv *drv_priv;
+	union drm_amdgpu_gem_mmap gem_map;
 
 	if (bo->priv)
 		return dri_bo_map(bo, vma, plane, map_flags);
 
-	drv_priv = bo->drv->priv;
-	gem_op.handle = handle;
-	gem_op.op = AMDGPU_GEM_OP_GET_GEM_CREATE_INFO;
-	gem_op.value = (uintptr_t)&bo_info;
+	memset(&gem_map, 0, sizeof(gem_map));
+	gem_map.in.handle = bo->handles[plane].u32;
 
-	ret = drmCommandWriteRead(bo->drv->fd, DRM_AMDGPU_GEM_OP, &gem_op, sizeof(gem_op));
-	if (ret)
-		return MAP_FAILED;
-
-	vma->length = bo_info.bo_size;
-
-	if (((bo_info.domains & AMDGPU_GEM_DOMAIN_VRAM) ||
-	     (bo_info.domain_flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC)) &&
-	    drv_priv->sdma_cmdbuf_map) {
-		union drm_amdgpu_gem_create gem_create = { { 0 } };
-
-		priv = calloc(1, sizeof(struct amdgpu_linear_vma_priv));
-		if (!priv)
-			return MAP_FAILED;
-
-		gem_create.in.bo_size = bo_info.bo_size;
-		gem_create.in.alignment = 4096;
-		gem_create.in.domains = AMDGPU_GEM_DOMAIN_GTT;
-
-		ret = drmCommandWriteRead(bo->drv->fd, DRM_AMDGPU_GEM_CREATE, &gem_create,
-					  sizeof(gem_create));
-		if (ret < 0) {
-			drv_log("GEM create failed\n");
-			free(priv);
-			return MAP_FAILED;
-		}
-
-		priv->map_flags = map_flags;
-		handle = priv->handle = gem_create.out.handle;
-
-		ret = sdma_copy(bo->drv->priv, bo->drv->fd, bo->handles[0].u32, priv->handle,
-				bo_info.bo_size);
-		if (ret) {
-			drv_log("SDMA copy for read failed\n");
-			goto fail;
-		}
-	}
-
-	gem_map.in.handle = handle;
 	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_AMDGPU_GEM_MMAP, &gem_map);
 	if (ret) {
 		drv_log("DRM_IOCTL_AMDGPU_GEM_MMAP failed\n");
-		goto fail;
+		return MAP_FAILED;
 	}
 
-	addr = mmap(0, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd,
+	vma->length = bo->meta.total_size;
+
+	return mmap(0, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd,
 		    gem_map.out.addr_ptr);
-	if (addr == MAP_FAILED)
-		goto fail;
-
-	vma->priv = priv;
-	return addr;
-
-fail:
-	if (priv) {
-		struct drm_gem_close gem_close = { 0 };
-		gem_close.handle = priv->handle;
-		drmIoctl(bo->drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
-		free(priv);
-	}
-	return MAP_FAILED;
 }
 
 static int amdgpu_unmap_bo(struct bo *bo, struct vma *vma)
 {
-	if (bo->priv) {
+	if (bo->priv)
 		return dri_bo_unmap(bo, vma);
-	} else {
-		int r = munmap(vma->addr, vma->length);
-		if (r)
-			return r;
-
-		if (vma->priv) {
-			struct amdgpu_linear_vma_priv *priv = vma->priv;
-			struct drm_gem_close gem_close = { 0 };
-
-			if (BO_MAP_WRITE & priv->map_flags) {
-				r = sdma_copy(bo->drv->priv, bo->drv->fd, priv->handle,
-					      bo->handles[0].u32, vma->length);
-				if (r)
-					return r;
-			}
-
-			gem_close.handle = priv->handle;
-			r = drmIoctl(bo->drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
-		}
-
-		return 0;
-	}
+	else
+		return munmap(vma->addr, vma->length);
 }
 
 static int amdgpu_bo_invalidate(struct bo *bo, struct mapping *mapping)
 {
 	int ret;
-	union drm_amdgpu_gem_wait_idle wait_idle = { { 0 } };
+	union drm_amdgpu_gem_wait_idle wait_idle;
 
 	if (bo->priv)
 		return 0;
 
+	memset(&wait_idle, 0, sizeof(wait_idle));
 	wait_idle.in.handle = bo->handles[0].u32;
 	wait_idle.in.timeout = AMDGPU_TIMEOUT_INFINITE;
 
@@ -707,6 +312,22 @@
 	return 0;
 }
 
+static uint32_t amdgpu_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags)
+{
+	switch (format) {
+	case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
+		/* Camera subsystem requires NV12. */
+		if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE))
+			return DRM_FORMAT_NV12;
+		/*HACK: See b/28671744 */
+		return DRM_FORMAT_XBGR8888;
+	case DRM_FORMAT_FLEX_YCbCr_420_888:
+		return DRM_FORMAT_NV12;
+	default:
+		return format;
+	}
+}
+
 const struct backend backend_amdgpu = {
 	.name = "amdgpu",
 	.init = amdgpu_init,
@@ -718,7 +339,7 @@
 	.bo_map = amdgpu_map_bo,
 	.bo_unmap = amdgpu_unmap_bo,
 	.bo_invalidate = amdgpu_bo_invalidate,
-	.resolve_format = drv_resolve_format_helper,
+	.resolve_format = amdgpu_resolve_format,
 	.num_planes_from_modifier = dri_num_planes_from_modifier,
 };
 
diff --git a/cros_gralloc/Makefile b/cros_gralloc/Makefile
index c95ad2c..17e884f 100644
--- a/cros_gralloc/Makefile
+++ b/cros_gralloc/Makefile
@@ -16,9 +16,9 @@
 LIBDRM_CFLAGS := $(shell $(PKG_CONFIG) --cflags libdrm)
 LIBDRM_LIBS := $(shell $(PKG_CONFIG) --libs libdrm)
 
-CPPFLAGS += -Wall -fPIC -Werror -flto $(LIBDRM_CFLAGS) -D_GNU_SOURCE=1
+CPPFLAGS += -Wall -fPIC -Werror -flto $(LIBDRM_CFLAGS)
 CXXFLAGS += -std=c++14
-CFLAGS   += -std=c99 -D_GNU_SOURCE=1
+CFLAGS   += -std=c99
 LIBS     += -shared -lcutils -lhardware -lsync $(LIBDRM_LIBS)
 
 OBJS =  $(foreach source, $(SOURCES), $(addsuffix .o, $(basename $(source))))
diff --git a/cros_gralloc/cros_gralloc_buffer.cc b/cros_gralloc/cros_gralloc_buffer.cc
index 2f4ceb0..2982505 100644
--- a/cros_gralloc/cros_gralloc_buffer.cc
+++ b/cros_gralloc/cros_gralloc_buffer.cc
@@ -26,8 +26,8 @@
 {
 	drv_bo_destroy(bo_);
 	if (hnd_) {
-		native_handle_close(hnd_);
-		native_handle_delete(hnd_);
+		native_handle_close(&hnd_->base);
+		delete hnd_;
 	}
 	if (reserved_region_addr_) {
 		munmap(reserved_region_addr_, reserved_region_size_);
@@ -116,10 +116,9 @@
 }
 
 int32_t cros_gralloc_buffer::resource_info(uint32_t strides[DRV_MAX_PLANES],
-					   uint32_t offsets[DRV_MAX_PLANES],
-					   uint64_t *format_modifier)
+					   uint32_t offsets[DRV_MAX_PLANES])
 {
-	return drv_resource_info(bo_, strides, offsets, format_modifier);
+	return drv_resource_info(bo_, strides, offsets);
 }
 
 int32_t cros_gralloc_buffer::invalidate()
@@ -129,8 +128,9 @@
 		return -EINVAL;
 	}
 
-	if (lock_data_[0])
+	if (lock_data_[0]) {
 		return drv_bo_invalidate(bo_, lock_data_[0]);
+	}
 
 	return 0;
 }
@@ -142,8 +142,9 @@
 		return -EINVAL;
 	}
 
-	if (lock_data_[0])
+	if (lock_data_[0]) {
 		return drv_bo_flush(bo_, lock_data_[0]);
+	}
 
 	return 0;
 }
diff --git a/cros_gralloc/cros_gralloc_buffer.h b/cros_gralloc/cros_gralloc_buffer.h
index 9bc0ef0..8634882 100644
--- a/cros_gralloc/cros_gralloc_buffer.h
+++ b/cros_gralloc/cros_gralloc_buffer.h
@@ -27,8 +27,7 @@
 	int32_t lock(const struct rectangle *rect, uint32_t map_flags,
 		     uint8_t *addr[DRV_MAX_PLANES]);
 	int32_t unlock();
-	int32_t resource_info(uint32_t strides[DRV_MAX_PLANES], uint32_t offsets[DRV_MAX_PLANES],
-			      uint64_t *format_modifier);
+	int32_t resource_info(uint32_t strides[DRV_MAX_PLANES], uint32_t offsets[DRV_MAX_PLANES]);
 
 	int32_t invalidate();
 	int32_t flush();
@@ -51,7 +50,7 @@
 
 	struct mapping *lock_data_[DRV_MAX_PLANES];
 
-	/* Optional additional shared memory region attached to some gralloc buffers. */
+	/* Optional additional shared memory region attached to some gralloc4 buffers. */
 	int32_t reserved_region_fd_;
 	uint64_t reserved_region_size_;
 	void *reserved_region_addr_;
diff --git a/cros_gralloc/cros_gralloc_driver.cc b/cros_gralloc/cros_gralloc_driver.cc
index f0c0392..e324bce 100644
--- a/cros_gralloc/cros_gralloc_driver.cc
+++ b/cros_gralloc/cros_gralloc_driver.cc
@@ -9,42 +9,12 @@
 #include <cstdlib>
 #include <fcntl.h>
 #include <sys/mman.h>
-#include <syscall.h>
 #include <xf86drm.h>
 
 #include "../drv_priv.h"
 #include "../helpers.h"
 #include "../util.h"
 
-// Constants taken from pipe_loader_drm.c in Mesa
-
-#define DRM_NUM_NODES 63
-
-// DRM Render nodes start at 128
-#define DRM_RENDER_NODE_START 128
-
-// DRM Card nodes start at 0
-#define DRM_CARD_NODE_START 0
-
-int memfd_create_wrapper(const char *name, unsigned int flags)
-{
-	int fd;
-
-#if defined(HAVE_MEMFD_CREATE)
-	fd = memfd_create(name, flags);
-#elif defined(__NR_memfd_create)
-	fd = syscall(__NR_memfd_create, name, flags);
-#else
-	drv_log("Failed to create memfd '%s': memfd_create not available.", name);
-	return -1;
-#endif
-
-	if (fd == -1)
-		drv_log("Failed to create memfd '%s': %s.\n", name, strerror(errno));
-
-	return fd;
-}
-
 cros_gralloc_driver::cros_gralloc_driver() : drv_(nullptr)
 {
 }
@@ -62,57 +32,54 @@
 	}
 }
 
-static struct driver *init_try_node(int idx, char const *str)
-{
-	int fd;
-	char *node;
-	struct driver *drv;
-
-	if (asprintf(&node, str, DRM_DIR_NAME, idx) < 0)
-		return NULL;
-
-	fd = open(node, O_RDWR, 0);
-	free(node);
-
-	if (fd < 0)
-		return NULL;
-
-	drv = drv_create(fd);
-	if (!drv)
-		close(fd);
-
-	return drv;
-}
-
 int32_t cros_gralloc_driver::init()
 {
 	/*
-	 * Create a driver from render nodes first, then try card
-	 * nodes.
+	 * Create a driver from rendernode while filtering out
+	 * the specified undesired driver.
 	 *
 	 * TODO(gsingh): Enable render nodes on udl/evdi.
 	 */
 
-	char const *render_nodes_fmt = "%s/renderD%d";
-	char const *card_nodes_fmt = "%s/card%d";
-	uint32_t num_nodes = DRM_NUM_NODES;
-	uint32_t min_render_node = DRM_RENDER_NODE_START;
-	uint32_t max_render_node = (min_render_node + num_nodes);
-	uint32_t min_card_node = DRM_CARD_NODE_START;
-	uint32_t max_card_node = (min_card_node + num_nodes);
+	int fd;
+	drmVersionPtr version;
+	char const *str = "%s/renderD%d";
+	const char *undesired[2] = { "vgem", nullptr };
+	uint32_t num_nodes = 63;
+	uint32_t min_node = 128;
+	uint32_t max_node = (min_node + num_nodes);
 
-	// Try render nodes...
-	for (uint32_t i = min_render_node; i < max_render_node; i++) {
-		drv_ = init_try_node(i, render_nodes_fmt);
-		if (drv_)
-			return 0;
-	}
+	for (uint32_t i = 0; i < ARRAY_SIZE(undesired); i++) {
+		for (uint32_t j = min_node; j < max_node; j++) {
+			char *node;
+			if (asprintf(&node, str, DRM_DIR_NAME, j) < 0)
+				continue;
 
-	// Try card nodes... for vkms mostly.
-	for (uint32_t i = min_card_node; i < max_card_node; i++) {
-		drv_ = init_try_node(i, card_nodes_fmt);
-		if (drv_)
-			return 0;
+			fd = open(node, O_RDWR, 0);
+			free(node);
+
+			if (fd < 0)
+				continue;
+
+			version = drmGetVersion(fd);
+			if (!version) {
+				close(fd);
+				continue;
+			}
+
+			if (undesired[i] && !strcmp(version->name, undesired[i])) {
+				close(fd);
+				drmFreeVersion(version);
+				continue;
+			}
+
+			drmFreeVersion(version);
+			drv_ = drv_create(fd);
+			if (drv_)
+				return 0;
+
+			close(fd);
+		}
 	}
 
 	return -ENODEV;
@@ -129,11 +96,14 @@
 
 int32_t create_reserved_region(const std::string &buffer_name, uint64_t reserved_region_size)
 {
+	int32_t reserved_region_fd;
 	std::string reserved_region_name = buffer_name + " reserved region";
 
-	int32_t reserved_region_fd = memfd_create_wrapper(reserved_region_name.c_str(), FD_CLOEXEC);
-	if (reserved_region_fd == -1)
+	reserved_region_fd = memfd_create(reserved_region_name.c_str(), FD_CLOEXEC);
+	if (reserved_region_fd == -1) {
+		drv_log("Failed to create reserved region fd: %s.\n", strerror(errno));
 		return -errno;
+	}
 
 	if (ftruncate(reserved_region_fd, reserved_region_size)) {
 		drv_log("Failed to set reserved region size: %s.\n", strerror(errno));
@@ -143,20 +113,10 @@
 	return reserved_region_fd;
 }
 
-void cros_gralloc_driver::emplace_buffer(struct bo *bo, struct cros_gralloc_handle *hnd)
-{
-	auto buffer = new cros_gralloc_buffer(hnd->id, bo, hnd, hnd->fds[hnd->num_planes],
-					      hnd->reserved_region_size);
-
-	std::lock_guard<std::mutex> lock(mutex_);
-	buffers_.emplace(hnd->id, buffer);
-	handles_.emplace(hnd, std::make_pair(buffer, 1));
-}
-
 int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descriptor *descriptor,
 				      buffer_handle_t *out_handle)
 {
-	int ret = 0;
+	uint32_t id;
 	size_t num_planes;
 	size_t num_fds;
 	size_t num_ints;
@@ -164,12 +124,22 @@
 	uint32_t resolved_format;
 	uint32_t bytes_per_pixel;
 	uint64_t use_flags;
+	int32_t reserved_region_fd;
 	char *name;
+
 	struct bo *bo;
 	struct cros_gralloc_handle *hnd;
 
 	resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags);
 	use_flags = descriptor->use_flags;
+	/*
+	 * TODO(b/79682290): ARC++ assumes NV12 is always linear and doesn't
+	 * send modifiers across Wayland protocol, so we or in the
+	 * BO_USE_LINEAR flag here. We need to fix ARC++ to allocate and work
+	 * with tiled buffers.
+	 */
+	if (resolved_format == DRM_FORMAT_NV12)
+		use_flags |= BO_USE_LINEAR;
 
 	/*
 	 * This unmask is a backup in the case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED is resolved
@@ -183,7 +153,7 @@
 	bo = drv_bo_create(drv_, descriptor->width, descriptor->height, resolved_format, use_flags);
 	if (!bo) {
 		drv_log("Failed to create bo.\n");
-		return -errno;
+		return -ENOMEM;
 	}
 
 	/*
@@ -192,15 +162,25 @@
 	 * send more than one fd. GL/Vulkan drivers may also have to modified.
 	 */
 	if (drv_num_buffers_per_bo(bo) != 1) {
+		drv_bo_destroy(bo);
 		drv_log("Can only support one buffer per bo.\n");
-		goto destroy_bo;
+		return -EINVAL;
 	}
 
 	num_planes = drv_bo_get_num_planes(bo);
 	num_fds = num_planes;
 
-	if (descriptor->reserved_region_size > 0)
+	if (descriptor->reserved_region_size > 0) {
+		reserved_region_fd =
+		    create_reserved_region(descriptor->name, descriptor->reserved_region_size);
+		if (reserved_region_fd < 0) {
+			drv_bo_destroy(bo);
+			return reserved_region_fd;
+		}
 		num_fds += 1;
+	} else {
+		reserved_region_fd = -1;
+	}
 
 	num_bytes = sizeof(struct cros_gralloc_handle);
 	num_bytes += (descriptor->name.size() + 1);
@@ -209,42 +189,30 @@
 	 * native_handle_clone() copies data based on hnd->base.numInts.
 	 */
 	num_bytes = ALIGN(num_bytes, sizeof(int));
-	num_ints = ((num_bytes - sizeof(native_handle_t)) / sizeof(int)) - num_fds;
-
-	hnd =
-	    reinterpret_cast<struct cros_gralloc_handle *>(native_handle_create(num_fds, num_ints));
-
-	for (size_t i = 0; i < DRV_MAX_FDS; i++)
-		hnd->fds[i] = -1;
-
+	num_ints = num_bytes - sizeof(native_handle_t) - num_fds;
+	/*
+	 * Malloc is used as handles are ultimetly destroyed via free in
+	 * native_handle_delete().
+	 */
+	hnd = static_cast<struct cros_gralloc_handle *>(malloc(num_bytes));
+	hnd->base.version = sizeof(hnd->base);
+	hnd->base.numFds = num_fds;
+	hnd->base.numInts = num_ints;
 	hnd->num_planes = num_planes;
 	for (size_t plane = 0; plane < num_planes; plane++) {
-		ret = drv_bo_get_plane_fd(bo, plane);
-		if (ret < 0)
-			goto destroy_hnd;
-
-		hnd->fds[plane] = ret;
+		hnd->fds[plane] = drv_bo_get_plane_fd(bo, plane);
 		hnd->strides[plane] = drv_bo_get_plane_stride(bo, plane);
 		hnd->offsets[plane] = drv_bo_get_plane_offset(bo, plane);
 		hnd->sizes[plane] = drv_bo_get_plane_size(bo, plane);
 	}
-
+	hnd->fds[hnd->num_planes] = reserved_region_fd;
 	hnd->reserved_region_size = descriptor->reserved_region_size;
-	if (hnd->reserved_region_size > 0) {
-		ret = create_reserved_region(descriptor->name, hnd->reserved_region_size);
-		if (ret < 0)
-			goto destroy_hnd;
-
-		hnd->fds[hnd->num_planes] = ret;
-	}
-
 	static std::atomic<uint32_t> next_buffer_id{ 1 };
 	hnd->id = next_buffer_id++;
 	hnd->width = drv_bo_get_width(bo);
 	hnd->height = drv_bo_get_height(bo);
 	hnd->format = drv_bo_get_format(bo);
-	hnd->tiling = bo->meta.tiling;
-	hnd->format_modifier = drv_bo_get_format_modifier(bo);
+	hnd->format_modifier = drv_bo_get_plane_format_modifier(bo, 0);
 	hnd->use_flags = descriptor->use_flags;
 	bytes_per_pixel = drv_bytes_per_pixel_from_format(hnd->format, 0);
 	hnd->pixel_stride = DIV_ROUND_UP(hnd->strides[0], bytes_per_pixel);
@@ -254,21 +222,18 @@
 	hnd->total_size = descriptor->reserved_region_size + bo->meta.total_size;
 	hnd->name_offset = handle_data_size;
 
-	name = (char *)(&hnd->data[hnd->name_offset]);
+	name = (char *)(&hnd->base.data[hnd->name_offset]);
 	snprintf(name, descriptor->name.size() + 1, "%s", descriptor->name.c_str());
 
-	emplace_buffer(bo, hnd);
+	id = drv_bo_get_plane_handle(bo, 0).u32;
+	auto buffer = new cros_gralloc_buffer(id, bo, hnd, hnd->fds[hnd->num_planes],
+					      hnd->reserved_region_size);
 
+	std::lock_guard<std::mutex> lock(mutex_);
+	buffers_.emplace(id, buffer);
+	handles_.emplace(hnd, std::make_pair(buffer, 1));
 	*out_handle = reinterpret_cast<buffer_handle_t>(hnd);
 	return 0;
-
-destroy_hnd:
-	native_handle_close(hnd);
-	native_handle_delete(hnd);
-
-destroy_bo:
-	drv_bo_destroy(bo);
-	return ret;
 }
 
 int32_t cros_gralloc_driver::retain(buffer_handle_t handle)
@@ -289,7 +254,10 @@
 		return 0;
 	}
 
-	id = hnd->id;
+	if (drmPrimeFDToHandle(drv_get_fd(drv_), hnd->fds[0], &id)) {
+		drv_log("drmPrimeFDToHandle failed.\n");
+		return -errno;
+	}
 
 	if (buffers_.count(id)) {
 		buffer = buffers_[id];
@@ -298,7 +266,6 @@
 		struct bo *bo;
 		struct drv_import_fd_data data;
 		data.format = hnd->format;
-		data.tiling = hnd->tiling;
 
 		data.width = hnd->width;
 		data.height = hnd->height;
@@ -307,12 +274,16 @@
 		memcpy(data.fds, hnd->fds, sizeof(data.fds));
 		memcpy(data.strides, hnd->strides, sizeof(data.strides));
 		memcpy(data.offsets, hnd->offsets, sizeof(data.offsets));
-		data.format_modifier = hnd->format_modifier;
+		for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++) {
+			data.format_modifiers[plane] = hnd->format_modifier;
+		}
 
 		bo = drv_bo_import(drv_, &data);
 		if (!bo)
 			return -EFAULT;
 
+		id = drv_bo_get_plane_handle(bo, 0).u32;
+
 		buffer = new cros_gralloc_buffer(id, bo, nullptr, hnd->fds[hnd->num_planes],
 						 hnd->reserved_region_size);
 		buffers_.emplace(id, buffer);
@@ -465,8 +436,7 @@
 }
 
 int32_t cros_gralloc_driver::resource_info(buffer_handle_t handle, uint32_t strides[DRV_MAX_PLANES],
-					   uint32_t offsets[DRV_MAX_PLANES],
-					   uint64_t *format_modifier)
+					   uint32_t offsets[DRV_MAX_PLANES])
 {
 	std::lock_guard<std::mutex> lock(mutex_);
 
@@ -482,7 +452,7 @@
 		return -EINVAL;
 	}
 
-	return buffer->resource_info(strides, offsets, format_modifier);
+	return buffer->resource_info(strides, offsets);
 }
 
 int32_t cros_gralloc_driver::get_reserved_region(buffer_handle_t handle,
@@ -525,6 +495,7 @@
 {
 	std::lock_guard<std::mutex> lock(mutex_);
 
-	for (const auto &pair : handles_)
+	for (const auto &pair : handles_) {
 		function(pair.first);
-}
+	}
+}
\ No newline at end of file
diff --git a/cros_gralloc/cros_gralloc_driver.h b/cros_gralloc/cros_gralloc_driver.h
index ef9e21f..d444ecd 100644
--- a/cros_gralloc/cros_gralloc_driver.h
+++ b/cros_gralloc/cros_gralloc_driver.h
@@ -37,7 +37,7 @@
 
 	int32_t get_backing_store(buffer_handle_t handle, uint64_t *out_store);
 	int32_t resource_info(buffer_handle_t handle, uint32_t strides[DRV_MAX_PLANES],
-			      uint32_t offsets[DRV_MAX_PLANES], uint64_t *format_modifier);
+			      uint32_t offsets[DRV_MAX_PLANES]);
 
 	int32_t get_reserved_region(buffer_handle_t handle, void **reserved_region_addr,
 				    uint64_t *reserved_region_size);
@@ -50,7 +50,6 @@
 	cros_gralloc_driver(cros_gralloc_driver const &);
 	cros_gralloc_driver operator=(cros_gralloc_driver const &);
 	cros_gralloc_buffer *get_buffer(cros_gralloc_handle_t hnd);
-	void emplace_buffer(struct bo *bo, struct cros_gralloc_handle *hnd);
 
 	struct driver *drv_;
 	std::mutex mutex_;
diff --git a/cros_gralloc/cros_gralloc_handle.h b/cros_gralloc/cros_gralloc_handle.h
index 2b70d4b..d2e1607 100644
--- a/cros_gralloc/cros_gralloc_handle.h
+++ b/cros_gralloc/cros_gralloc_handle.h
@@ -13,7 +13,8 @@
 #define DRV_MAX_PLANES 4
 #define DRV_MAX_FDS (DRV_MAX_PLANES + 1)
 
-struct cros_gralloc_handle : public native_handle_t {
+struct cros_gralloc_handle {
+	native_handle_t base;
 	/*
 	 * File descriptors must immediately follow the native_handle_t base and used file
 	 * descriptors must be packed at the beginning of this array to work with
@@ -30,7 +31,6 @@
 	uint32_t width;
 	uint32_t height;
 	uint32_t format; /* DRM format */
-	uint32_t tiling;
 	uint64_t format_modifier;
 	uint64_t use_flags; /* Buffer creation flags */
 	uint32_t magic;
diff --git a/cros_gralloc/cros_gralloc_helpers.cc b/cros_gralloc/cros_gralloc_helpers.cc
index 4319936..1e05150 100644
--- a/cros_gralloc/cros_gralloc_helpers.cc
+++ b/cros_gralloc/cros_gralloc_helpers.cc
@@ -90,10 +90,3 @@
 
 	return 0;
 }
-
-std::string get_drm_format_string(uint32_t drm_format)
-{
-	char *sequence = (char *)&drm_format;
-	std::string s(sequence, 4);
-	return "DRM_FOURCC_" + s;
-}
diff --git a/cros_gralloc/cros_gralloc_helpers.h b/cros_gralloc/cros_gralloc_helpers.h
index a43833d..36f86ef 100644
--- a/cros_gralloc/cros_gralloc_helpers.h
+++ b/cros_gralloc/cros_gralloc_helpers.h
@@ -24,6 +24,4 @@
 
 int32_t cros_gralloc_sync_wait(int32_t fence, bool close_fence);
 
-std::string get_drm_format_string(uint32_t drm_format);
-
 #endif
diff --git a/cros_gralloc/gralloc0/gralloc0.cc b/cros_gralloc/gralloc0/gralloc0.cc
index 5899d5a..170dae9 100644
--- a/cros_gralloc/gralloc0/gralloc0.cc
+++ b/cros_gralloc/gralloc0/gralloc0.cc
@@ -4,7 +4,6 @@
  * found in the LICENSE file.
  */
 
-#include "../../helpers.h"
 #include "../../util.h"
 #include "../cros_gralloc_driver.h"
 
@@ -20,15 +19,6 @@
 	std::mutex initialization_mutex;
 };
 
-struct cros_gralloc0_buffer_info {
-	uint32_t drm_fourcc;
-	int num_fds;
-	int fds[4];
-	uint64_t modifier;
-	uint32_t offset[4];
-	uint32_t stride[4];
-};
-
 /* This enumeration must match the one in <gralloc_drm.h>.
  * The functions supported by this gralloc's temporary private API are listed
  * below. Use of these functions is highly discouraged and should only be
@@ -41,23 +31,6 @@
 	GRALLOC_DRM_GET_FORMAT,
 	GRALLOC_DRM_GET_DIMENSIONS,
 	GRALLOC_DRM_GET_BACKING_STORE,
-	GRALLOC_DRM_GET_BUFFER_INFO,
-	GRALLOC_DRM_GET_USAGE,
-};
-
-/* This enumeration corresponds to the GRALLOC_DRM_GET_USAGE query op, which
- * defines a set of bit flags used by the client to query vendor usage bits.
- *
- * Here is the common flow:
- * 1) EGL/Vulkan calls GRALLOC_DRM_GET_USAGE to append one or multiple vendor
- *    usage bits to the existing usage and sets onto the ANativeWindow.
- * 2) Some implicit GL draw cmd or the explicit vkCreateSwapchainKHR kicks off
- *    the next dequeueBuffer on the ANativeWindow with the combined usage.
- * 3) dequeueBuffer then asks gralloc hal for an allocation/re-allocation, and
- *    calls into the below `gralloc0_alloc(...)` api.
- */
-enum {
-	GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT = 0x00000001,
 };
 // clang-format on
 
@@ -66,11 +39,6 @@
 // entirety, so we can detect the video decoder flag passed by IAllocator clients.
 #define BUFFER_USAGE_VIDEO_DECODER (1 << 22)
 
-// Reserve the GRALLOC_USAGE_PRIVATE_0 bit for buffers used for front rendering.
-// minigbm backend later decides to use BO_USE_FRONT_RENDERING or BO_USE_LINEAR
-// upon buffer allocaton.
-#define BUFFER_USAGE_FRONT_RENDERING GRALLOC_USAGE_PRIVATE_0
-
 static uint64_t gralloc0_convert_usage(int usage)
 {
 	uint64_t use_flags = BO_USE_NONE;
@@ -102,9 +70,8 @@
 		 * rockchip) and usb monitors (evdi/udl). It's complicated so ignore it.
 		 * */
 		use_flags |= BO_USE_NONE;
-	/* Map this flag to linear until real HW protection is available on Android. */
 	if (usage & GRALLOC_USAGE_PROTECTED)
-		use_flags |= BO_USE_LINEAR;
+		use_flags |= BO_USE_PROTECTED;
 	if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) {
 		use_flags |= BO_USE_HW_VIDEO_ENCODER;
 		/*HACK: See b/30054495 */
@@ -118,8 +85,6 @@
 		use_flags |= BO_USE_RENDERSCRIPT;
 	if (usage & BUFFER_USAGE_VIDEO_DECODER)
 		use_flags |= BO_USE_HW_VIDEO_DECODER;
-	if (usage & BUFFER_USAGE_FRONT_RENDERING)
-		use_flags |= BO_USE_FRONT_RENDERING;
 
 	return use_flags;
 }
@@ -165,18 +130,11 @@
 		supported = mod->driver->is_supported(&descriptor);
 	}
 	if (!supported && (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) &&
-	    format != HAL_PIXEL_FORMAT_YCbCr_420_888) {
-		// Unmask BO_USE_HW_VIDEO_ENCODER for other formats. They are mostly
-		// intermediate formats not passed directly to the encoder (e.g.
-		// camera). YV12 is passed to the encoder component, but it is converted
-		// to YCbCr_420_888 before being passed to the hw encoder.
+	    !gralloc0_droid_yuv_format(format)) {
+		// Unmask BO_USE_HW_VIDEO_ENCODER in the case of non-yuv formats
+		// because they are not input to a hw encoder but used as an
+		// intermediate format (e.g. camera).
 		descriptor.use_flags &= ~BO_USE_HW_VIDEO_ENCODER;
-		drv_log("Retrying format %u allocation without encoder flag", format);
-		supported = mod->driver->is_supported(&descriptor);
-	}
-	if (!supported && (usage & BUFFER_USAGE_FRONT_RENDERING)) {
-		descriptor.use_flags &= ~BO_USE_FRONT_RENDERING;
-		descriptor.use_flags |= BO_USE_LINEAR;
 		supported = mod->driver->is_supported(&descriptor);
 	}
 
@@ -264,10 +222,9 @@
 	auto const_module = reinterpret_cast<const struct gralloc0_module *>(module);
 	auto mod = const_cast<struct gralloc0_module *>(const_module);
 
-	if (!mod->initialized) {
+	if (!mod->initialized)
 		if (gralloc0_init(mod, false))
 			return -ENODEV;
-	}
 
 	return mod->driver->retain(handle);
 }
@@ -305,52 +262,35 @@
 	int32_t *out_format, ret;
 	uint64_t *out_store;
 	buffer_handle_t handle;
-	cros_gralloc_handle_t hnd;
 	uint32_t *out_width, *out_height, *out_stride;
 	uint32_t strides[DRV_MAX_PLANES] = { 0, 0, 0, 0 };
 	uint32_t offsets[DRV_MAX_PLANES] = { 0, 0, 0, 0 };
-	uint64_t format_modifier = 0;
-	struct cros_gralloc0_buffer_info *info;
-	auto const_module = reinterpret_cast<const struct gralloc0_module *>(module);
-	auto mod = const_cast<struct gralloc0_module *>(const_module);
-	uint32_t req_usage;
-	uint32_t gralloc_usage = 0;
-	uint32_t *out_gralloc_usage;
-
-	if (!mod->initialized) {
-		if (gralloc0_init(mod, false))
-			return -ENODEV;
-	}
-
-	va_start(args, op);
+	auto mod = (struct gralloc0_module const *)module;
 
 	switch (op) {
 	case GRALLOC_DRM_GET_STRIDE:
 	case GRALLOC_DRM_GET_FORMAT:
 	case GRALLOC_DRM_GET_DIMENSIONS:
 	case GRALLOC_DRM_GET_BACKING_STORE:
-	case GRALLOC_DRM_GET_BUFFER_INFO:
-		/* retrieve handles for ops with buffer_handle_t */
-		handle = va_arg(args, buffer_handle_t);
-		hnd = cros_gralloc_convert_handle(handle);
-		if (!hnd) {
-			va_end(args);
-			drv_log("Invalid handle.\n");
-			return -EINVAL;
-		}
-		break;
-	case GRALLOC_DRM_GET_USAGE:
 		break;
 	default:
-		va_end(args);
 		return -EINVAL;
 	}
 
+	va_start(args, op);
+
 	ret = 0;
+	handle = va_arg(args, buffer_handle_t);
+	auto hnd = cros_gralloc_convert_handle(handle);
+	if (!hnd) {
+		drv_log("Invalid handle.\n");
+		return -EINVAL;
+	}
+
 	switch (op) {
 	case GRALLOC_DRM_GET_STRIDE:
 		out_stride = va_arg(args, uint32_t *);
-		ret = mod->driver->resource_info(handle, strides, offsets, &format_modifier);
+		ret = mod->driver->resource_info(handle, strides, offsets);
 		if (ret)
 			break;
 
@@ -376,34 +316,6 @@
 		out_store = va_arg(args, uint64_t *);
 		ret = mod->driver->get_backing_store(handle, out_store);
 		break;
-	case GRALLOC_DRM_GET_BUFFER_INFO:
-		info = va_arg(args, struct cros_gralloc0_buffer_info *);
-		memset(info, 0, sizeof(*info));
-		info->drm_fourcc = drv_get_standard_fourcc(hnd->format);
-		info->num_fds = hnd->num_planes;
-		ret = mod->driver->resource_info(handle, strides, offsets, &format_modifier);
-		if (ret)
-			break;
-
-		info->modifier = format_modifier ? format_modifier : hnd->format_modifier;
-		for (uint32_t i = 0; i < hnd->num_planes; i++) {
-			info->fds[i] = hnd->fds[i];
-			if (strides[i]) {
-				info->stride[i] = strides[i];
-				info->offset[i] = offsets[i];
-			} else {
-				info->stride[i] = hnd->strides[i];
-				info->offset[i] = hnd->offsets[i];
-			}
-		}
-		break;
-	case GRALLOC_DRM_GET_USAGE:
-		req_usage = va_arg(args, uint32_t);
-		out_gralloc_usage = va_arg(args, uint32_t *);
-		if (req_usage & GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT)
-			gralloc_usage |= BUFFER_USAGE_FRONT_RENDERING;
-		*out_gralloc_usage = gralloc_usage;
-		break;
 	default:
 		ret = -EINVAL;
 	}
@@ -425,18 +337,12 @@
 	int32_t ret;
 	uint32_t map_flags;
 	uint8_t *addr[DRV_MAX_PLANES];
-	auto const_module = reinterpret_cast<const struct gralloc0_module *>(module);
-	auto mod = const_cast<struct gralloc0_module *>(const_module);
+	auto mod = (struct gralloc0_module const *)module;
 	struct rectangle rect = { .x = static_cast<uint32_t>(l),
 				  .y = static_cast<uint32_t>(t),
 				  .width = static_cast<uint32_t>(w),
 				  .height = static_cast<uint32_t>(h) };
 
-	if (!mod->initialized) {
-		if (gralloc0_init(mod, false))
-			return -ENODEV;
-	}
-
 	auto hnd = cros_gralloc_convert_handle(handle);
 	if (!hnd) {
 		drv_log("Invalid handle.\n");
@@ -474,20 +380,13 @@
 	uint32_t map_flags;
 	uint32_t strides[DRV_MAX_PLANES] = { 0, 0, 0, 0 };
 	uint32_t offsets[DRV_MAX_PLANES] = { 0, 0, 0, 0 };
-	uint64_t format_modifier = 0;
 	uint8_t *addr[DRV_MAX_PLANES] = { nullptr, nullptr, nullptr, nullptr };
-	auto const_module = reinterpret_cast<const struct gralloc0_module *>(module);
-	auto mod = const_cast<struct gralloc0_module *>(const_module);
+	auto mod = (struct gralloc0_module const *)module;
 	struct rectangle rect = { .x = static_cast<uint32_t>(l),
 				  .y = static_cast<uint32_t>(t),
 				  .width = static_cast<uint32_t>(w),
 				  .height = static_cast<uint32_t>(h) };
 
-	if (!mod->initialized) {
-		if (gralloc0_init(mod, false))
-			return -ENODEV;
-	}
-
 	auto hnd = cros_gralloc_convert_handle(handle);
 	if (!hnd) {
 		drv_log("Invalid handle.\n");
@@ -511,7 +410,7 @@
 		return ret;
 
 	if (!map_flags) {
-		ret = mod->driver->resource_info(handle, strides, offsets, &format_modifier);
+		ret = mod->driver->resource_info(handle, strides, offsets);
 		if (ret)
 			return ret;
 
diff --git a/cros_gralloc/gralloc0/tests/gralloctest.c b/cros_gralloc/gralloc0/tests/gralloctest.c
index eea36e4..f663cd0 100644
--- a/cros_gralloc/gralloc0/tests/gralloctest.c
+++ b/cros_gralloc/gralloc0/tests/gralloctest.c
@@ -41,20 +41,12 @@
 		}                                                                                  \
 	} while (0)
 
-#define BUFFER_USAGE_FRONT_RENDERING GRALLOC_USAGE_PRIVATE_0
-
 /* Private API enumeration -- see <gralloc_drm.h> */
 enum {
 	GRALLOC_DRM_GET_STRIDE,
 	GRALLOC_DRM_GET_FORMAT,
 	GRALLOC_DRM_GET_DIMENSIONS,
 	GRALLOC_DRM_GET_BACKING_STORE,
-	GRALLOC_DRM_GET_BUFFER_INFO,
-	GRALLOC_DRM_GET_USAGE,
-};
-
-enum {
-	GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT = 0x00000001,
 };
 
 struct gralloctest_context {
@@ -475,7 +467,7 @@
 {
 	int32_t format;
 	uint64_t id1, id2;
-	uint32_t stride, width, height, req_usage, gralloc_usage;
+	uint32_t stride, width, height;
 	struct grallocinfo info, duplicate;
 	struct gralloc_module_t *mod = ctx->module;
 
@@ -484,7 +476,7 @@
 	CHECK(allocate(ctx->device, &info));
 
 	CHECK(mod->perform(mod, GRALLOC_DRM_GET_STRIDE, info.handle, &stride) == 0);
-	CHECK(stride >= info.stride);
+	CHECK(stride == info.stride);
 
 	CHECK(mod->perform(mod, GRALLOC_DRM_GET_FORMAT, info.handle, &format) == 0);
 	CHECK(format == info.format);
@@ -506,16 +498,6 @@
 	CHECK(unregister_buffer(mod, &duplicate));
 	CHECK(deallocate(ctx->device, &info));
 
-	req_usage = 0;
-	gralloc_usage = 0;
-	CHECK(mod->perform(mod, GRALLOC_DRM_GET_USAGE, req_usage, &gralloc_usage) == 0);
-	CHECK(gralloc_usage == 0);
-
-	req_usage = GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT;
-	gralloc_usage = 0;
-	CHECK(mod->perform(mod, GRALLOC_DRM_GET_USAGE, req_usage, &gralloc_usage) == 0);
-	CHECK(gralloc_usage == BUFFER_USAGE_FRONT_RENDERING);
-
 	return 1;
 }
 
@@ -692,12 +674,11 @@
 			if (strcmp(tests[i].name, name) && strcmp("all", name))
 				continue;
 
-			printf("[ RUN      ] gralloctest.%s\n", tests[i].name);
-
 			int success = 1;
 			if (ctx->api >= tests[i].required_api)
 				success = tests[i].run_test(ctx);
 
+			printf("[ RUN      ] gralloctest.%s\n", tests[i].name);
 			if (!success) {
 				fprintf(stderr, "[  FAILED  ] gralloctest.%s\n", tests[i].name);
 				ret |= 1;
diff --git a/cros_gralloc/gralloc3/.clang-format b/cros_gralloc/gralloc3/.clang-format
deleted file mode 100644
index 534cd32..0000000
--- a/cros_gralloc/gralloc3/.clang-format
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2020 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This directory is formatted to match the format of the interfaces implemented.
-
-BasedOnStyle: Google
-Standard: Cpp11
-AccessModifierOffset: -2
-AllowShortFunctionsOnASingleLine: Inline
-ColumnLimit: 100
-CommentPragmas: NOLINT:.*
-DerivePointerAlignment: false
-IncludeBlocks: Preserve
-IndentWidth: 4
-ContinuationIndentWidth: 8
-PointerAlignment: Left
-TabWidth: 4
-UseTab: Never
\ No newline at end of file
diff --git a/cros_gralloc/gralloc3/Android.bp b/cros_gralloc/gralloc3/Android.bp
deleted file mode 100644
index 6e36c5b..0000000
--- a/cros_gralloc/gralloc3/Android.bp
+++ /dev/null
@@ -1,88 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "external_minigbm_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-BSD
-    default_applicable_licenses: ["external_minigbm_license"],
-}
-
-cc_binary {
-    name: "android.hardware.graphics.allocator@3.0-service.minigbm",
-    relative_install_path: "hw",
-    vendor: true,
-    init_rc: ["android.hardware.graphics.allocator@3.0-service.minigbm.rc"],
-
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-
-    shared_libs: [
-        "android.hardware.graphics.allocator@3.0",
-        "android.hardware.graphics.mapper@3.0",
-        "libbase",
-        "libcutils",
-        "libhidlbase",
-        "liblog",
-        "libsync",
-        "libutils",
-    ],
-
-    static_libs: [
-        "libdrm",
-        "libminigbm_cros_gralloc",
-    ],
-
-    srcs: [
-        "CrosGralloc3Allocator.cc",
-        "CrosGralloc3AllocatorService.cc",
-        "CrosGralloc3Utils.cc",
-    ],
-}
-
-cc_library_shared {
-    name: "android.hardware.graphics.mapper@3.0-impl.minigbm",
-    relative_install_path: "hw",
-    vendor: true,
-
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-
-    shared_libs: [
-        "android.hardware.graphics.mapper@3.0",
-        "libbase",
-        "libcutils",
-        "libhidlbase",
-        "liblog",
-        "libsync",
-        "libutils",
-    ],
-
-    static_libs: [
-        "libdrm",
-        "libminigbm_cros_gralloc",
-    ],
-
-    srcs: [
-        "CrosGralloc3Mapper.cc",
-        "CrosGralloc3Utils.cc",
-    ],
-}
diff --git a/cros_gralloc/gralloc3/CrosGralloc3Allocator.cc b/cros_gralloc/gralloc3/CrosGralloc3Allocator.cc
deleted file mode 100644
index 57c49e9..0000000
--- a/cros_gralloc/gralloc3/CrosGralloc3Allocator.cc
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright 2020 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "cros_gralloc/gralloc3/CrosGralloc3Allocator.h"
-
-#include <optional>
-
-#include <android/hardware/graphics/mapper/3.0/IMapper.h>
-
-#include "cros_gralloc/cros_gralloc_helpers.h"
-#include "cros_gralloc/gralloc3/CrosGralloc3Utils.h"
-
-using android::hardware::hidl_handle;
-using android::hardware::hidl_vec;
-using android::hardware::Return;
-using android::hardware::Void;
-using android::hardware::graphics::common::V1_2::BufferUsage;
-using android::hardware::graphics::common::V1_2::PixelFormat;
-using android::hardware::graphics::mapper::V3_0::Error;
-
-using BufferDescriptorInfo =
-        android::hardware::graphics::mapper::V3_0::IMapper::BufferDescriptorInfo;
-
-CrosGralloc3Allocator::CrosGralloc3Allocator() : mDriver(std::make_unique<cros_gralloc_driver>()) {
-    if (mDriver->init()) {
-        drv_log("Failed to initialize driver.\n");
-        mDriver = nullptr;
-    }
-}
-
-Error CrosGralloc3Allocator::allocate(const BufferDescriptorInfo& descriptor, uint32_t* outStride,
-                                      hidl_handle* outHandle) {
-    if (!mDriver) {
-        drv_log("Failed to allocate. Driver is uninitialized.\n");
-        return Error::NO_RESOURCES;
-    }
-
-    if (!outStride || !outHandle) {
-        return Error::NO_RESOURCES;
-    }
-
-    struct cros_gralloc_buffer_descriptor crosDescriptor;
-    if (convertToCrosDescriptor(descriptor, &crosDescriptor)) {
-        return Error::UNSUPPORTED;
-    }
-
-    bool supported = mDriver->is_supported(&crosDescriptor);
-    if (!supported && (descriptor.usage & BufferUsage::COMPOSER_OVERLAY)) {
-        crosDescriptor.use_flags &= ~BO_USE_SCANOUT;
-        supported = mDriver->is_supported(&crosDescriptor);
-    }
-
-    if (!supported) {
-        std::string drmFormatString = get_drm_format_string(crosDescriptor.drm_format);
-        std::string pixelFormatString = getPixelFormatString(descriptor.format);
-        std::string usageString = getUsageString(descriptor.usage);
-        drv_log("Unsupported combination -- pixel format: %s, drm format:%s, usage: %s\n",
-                pixelFormatString.c_str(), drmFormatString.c_str(), usageString.c_str());
-        return Error::UNSUPPORTED;
-    }
-
-    buffer_handle_t handle;
-    int ret = mDriver->allocate(&crosDescriptor, &handle);
-    if (ret) {
-        return Error::NO_RESOURCES;
-    }
-
-    cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(handle);
-    if (!crosHandle) {
-        return Error::NO_RESOURCES;
-    }
-
-    *outHandle = handle;
-    *outStride = crosHandle->pixel_stride;
-
-    return Error::NONE;
-}
-
-Return<void> CrosGralloc3Allocator::allocate(const hidl_vec<uint32_t>& encoded, uint32_t count,
-                                             allocate_cb hidlCb) {
-    hidl_vec<hidl_handle> handles;
-
-    if (!mDriver) {
-        drv_log("Failed to allocate. Driver is uninitialized.\n");
-        hidlCb(Error::NO_RESOURCES, 0, handles);
-        return Void();
-    }
-
-    auto descriptor_opt = decodeBufferDescriptorInfo(encoded);
-    if (!descriptor_opt) {
-        drv_log("Failed to allocate. Failed to decode buffer descriptor.\n");
-        hidlCb(Error::BAD_DESCRIPTOR, 0, handles);
-        return Void();
-    }
-
-    BufferDescriptorInfo descriptor = *descriptor_opt;
-
-    handles.resize(count);
-
-    uint32_t stride = 0;
-    for (int i = 0; i < handles.size(); i++) {
-        Error err = allocate(descriptor, &stride, &(handles[i]));
-        if (err != Error::NONE) {
-            for (int j = 0; j < i; j++) {
-                mDriver->release(handles[j].getNativeHandle());
-            }
-            handles.resize(0);
-            hidlCb(err, 0, handles);
-            return Void();
-        }
-    }
-
-    hidlCb(Error::NONE, stride, handles);
-
-    for (const hidl_handle& handle : handles) {
-        mDriver->release(handle.getNativeHandle());
-    }
-
-    return Void();
-}
-
-Return<void> CrosGralloc3Allocator::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) {
-    hidl_cb("CrosGralloc3Allocator::dumpDebugInfo unimplemented.");
-    return Void();
-}
diff --git a/cros_gralloc/gralloc3/CrosGralloc3Allocator.h b/cros_gralloc/gralloc3/CrosGralloc3Allocator.h
deleted file mode 100644
index 655143c..0000000
--- a/cros_gralloc/gralloc3/CrosGralloc3Allocator.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2020 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/3.0/IMapper.h>
-
-#include "cros_gralloc/cros_gralloc_driver.h"
-
-class CrosGralloc3Allocator : public android::hardware::graphics::allocator::V3_0::IAllocator {
-  public:
-    CrosGralloc3Allocator();
-
-    android::hardware::Return<void> allocate(
-            const android::hardware::hidl_vec<uint32_t>& descriptor, uint32_t count,
-            allocate_cb hidl_cb) override;
-
-    android::hardware::Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
-
-  private:
-    android::hardware::graphics::mapper::V3_0::Error allocate(
-            const android::hardware::graphics::mapper::V3_0::IMapper::BufferDescriptorInfo&
-                    description,
-            uint32_t* outStride, android::hardware::hidl_handle* outHandle);
-
-    std::unique_ptr<cros_gralloc_driver> mDriver;
-};
diff --git a/cros_gralloc/gralloc3/CrosGralloc3AllocatorService.cc b/cros_gralloc/gralloc3/CrosGralloc3AllocatorService.cc
deleted file mode 100644
index daab508..0000000
--- a/cros_gralloc/gralloc3/CrosGralloc3AllocatorService.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2020 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#define LOG_TAG "AllocatorService"
-
-#include <hidl/LegacySupport.h>
-
-#include "cros_gralloc/gralloc3/CrosGralloc3Allocator.h"
-
-using android::sp;
-using android::hardware::configureRpcThreadpool;
-using android::hardware::joinRpcThreadpool;
-using android::hardware::graphics::allocator::V3_0::IAllocator;
-
-int main(int, char**) {
-    sp<IAllocator> allocator = new CrosGralloc3Allocator();
-    configureRpcThreadpool(4, true /* callerWillJoin */);
-    if (allocator->registerAsService() != android::NO_ERROR) {
-        ALOGE("failed to register graphics IAllocator 3.0 service");
-        return -EINVAL;
-    }
-
-    ALOGI("graphics IAllocator 3.0 service is initialized");
-    android::hardware::joinRpcThreadpool();
-    ALOGI("graphics IAllocator 3.0 service is terminating");
-    return 0;
-}
diff --git a/cros_gralloc/gralloc3/CrosGralloc3Mapper.cc b/cros_gralloc/gralloc3/CrosGralloc3Mapper.cc
deleted file mode 100644
index 08da016..0000000
--- a/cros_gralloc/gralloc3/CrosGralloc3Mapper.cc
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * Copyright 2020 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "cros_gralloc/gralloc3/CrosGralloc3Mapper.h"
-
-#include <cutils/native_handle.h>
-
-#include "cros_gralloc/cros_gralloc_helpers.h"
-#include "cros_gralloc/gralloc3/CrosGralloc3Utils.h"
-
-#include "helpers.h"
-
-using android::hardware::hidl_handle;
-using android::hardware::hidl_vec;
-using android::hardware::Return;
-using android::hardware::Void;
-using android::hardware::graphics::common::V1_2::BufferUsage;
-using android::hardware::graphics::common::V1_2::PixelFormat;
-using android::hardware::graphics::mapper::V3_0::Error;
-using android::hardware::graphics::mapper::V3_0::IMapper;
-using android::hardware::graphics::mapper::V3_0::YCbCrLayout;
-
-CrosGralloc3Mapper::CrosGralloc3Mapper() : mDriver(std::make_unique<cros_gralloc_driver>()) {
-    if (mDriver->init()) {
-        drv_log("Failed to initialize driver.\n");
-        mDriver = nullptr;
-    }
-}
-
-Return<void> CrosGralloc3Mapper::createDescriptor(const BufferDescriptorInfo& description,
-                                                  createDescriptor_cb hidlCb) {
-    hidl_vec<uint32_t> descriptor;
-
-    if (description.width == 0) {
-        drv_log("Failed to createDescriptor. Bad width: %d.\n", description.width);
-        hidlCb(Error::BAD_VALUE, descriptor);
-        return Void();
-    }
-
-    if (description.height == 0) {
-        drv_log("Failed to createDescriptor. Bad height: %d.\n", description.height);
-        hidlCb(Error::BAD_VALUE, descriptor);
-        return Void();
-    }
-
-    if (description.layerCount == 0) {
-        drv_log("Failed to createDescriptor. Bad layer count: %d.\n", description.layerCount);
-        hidlCb(Error::BAD_VALUE, descriptor);
-        return Void();
-    }
-
-    auto descriptor_opt = encodeBufferDescriptorInfo(description);
-    if (!descriptor_opt) {
-        drv_log("Failed to createDescriptor. Failed to encodeBufferDescriptorInfo\n");
-        hidlCb(Error::BAD_VALUE, descriptor);
-        return Void();
-    }
-
-    descriptor = *descriptor_opt;
-    hidlCb(Error::NONE, descriptor);
-    return Void();
-}
-
-Return<void> CrosGralloc3Mapper::importBuffer(const hidl_handle& handle, importBuffer_cb hidlCb) {
-    if (!mDriver) {
-        drv_log("Failed to import buffer. Driver is uninitialized.\n");
-        hidlCb(Error::NO_RESOURCES, nullptr);
-        return Void();
-    }
-
-    const native_handle_t* bufferHandle = handle.getNativeHandle();
-    if (!bufferHandle || bufferHandle->numFds == 0) {
-        drv_log("Failed to importBuffer. Bad handle.\n");
-        hidlCb(Error::BAD_BUFFER, nullptr);
-        return Void();
-    }
-
-    native_handle_t* importedBufferHandle = native_handle_clone(bufferHandle);
-    if (!importedBufferHandle) {
-        drv_log("Failed to importBuffer. Handle clone failed.\n");
-        hidlCb(Error::NO_RESOURCES, nullptr);
-        return Void();
-    }
-
-    int ret = mDriver->retain(importedBufferHandle);
-    if (ret) {
-        native_handle_close(importedBufferHandle);
-        native_handle_delete(importedBufferHandle);
-        hidlCb(Error::NO_RESOURCES, nullptr);
-        return Void();
-    }
-
-    hidlCb(Error::NONE, importedBufferHandle);
-    return Void();
-}
-
-Return<Error> CrosGralloc3Mapper::freeBuffer(void* rawHandle) {
-    if (!mDriver) {
-        drv_log("Failed to freeBuffer. Driver is uninitialized.\n");
-        return Error::NO_RESOURCES;
-    }
-
-    native_handle_t* bufferHandle = reinterpret_cast<native_handle_t*>(rawHandle);
-    if (!bufferHandle) {
-        drv_log("Failed to freeBuffer. Empty handle.\n");
-        return Error::BAD_BUFFER;
-    }
-
-    int ret = mDriver->release(bufferHandle);
-    if (ret) {
-        drv_log("Failed to freeBuffer.\n");
-        return Error::BAD_BUFFER;
-    }
-
-    native_handle_close(bufferHandle);
-    native_handle_delete(bufferHandle);
-    return Error::NONE;
-}
-
-Return<Error> CrosGralloc3Mapper::validateBufferSize(void* rawHandle,
-                                                     const BufferDescriptorInfo& descriptor,
-                                                     uint32_t stride) {
-    if (!mDriver) {
-        drv_log("Failed to validateBufferSize. Driver is uninitialized.\n");
-        return Error::NO_RESOURCES;
-    }
-
-    native_handle_t* bufferHandle = reinterpret_cast<native_handle_t*>(rawHandle);
-    if (!bufferHandle) {
-        drv_log("Failed to validateBufferSize. Empty handle.\n");
-        return Error::BAD_BUFFER;
-    }
-
-    cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle);
-    if (!crosHandle) {
-        drv_log("Failed to validateBufferSize. Invalid handle.\n");
-        return Error::BAD_BUFFER;
-    }
-
-    PixelFormat crosHandleFormat = static_cast<PixelFormat>(crosHandle->droid_format);
-    if (descriptor.format != crosHandleFormat) {
-        drv_log("Failed to validateBufferSize. Format mismatch.\n");
-        return Error::BAD_BUFFER;
-    }
-
-    if (descriptor.width != crosHandle->width) {
-        drv_log("Failed to validateBufferSize. Width mismatch (%d vs %d).\n", descriptor.width,
-                crosHandle->width);
-        return Error::BAD_VALUE;
-    }
-
-    if (descriptor.height != crosHandle->height) {
-        drv_log("Failed to validateBufferSize. Height mismatch (%d vs %d).\n", descriptor.height,
-                crosHandle->height);
-        return Error::BAD_VALUE;
-    }
-
-    if (stride != crosHandle->pixel_stride) {
-        drv_log("Failed to validateBufferSize. Stride mismatch (%d vs %d).\n", stride,
-                crosHandle->pixel_stride);
-        return Error::BAD_VALUE;
-    }
-
-    return Error::NONE;
-}
-
-Return<void> CrosGralloc3Mapper::getTransportSize(void* rawHandle, getTransportSize_cb hidlCb) {
-    if (!mDriver) {
-        drv_log("Failed to getTransportSize. Driver is uninitialized.\n");
-        hidlCb(Error::BAD_BUFFER, 0, 0);
-        return Void();
-    }
-
-    native_handle_t* bufferHandle = reinterpret_cast<native_handle_t*>(rawHandle);
-    if (!bufferHandle) {
-        drv_log("Failed to getTransportSize. Bad handle.\n");
-        hidlCb(Error::BAD_BUFFER, 0, 0);
-        return Void();
-    }
-
-    // No local process data is currently stored on the native handle.
-    hidlCb(Error::NONE, bufferHandle->numFds, bufferHandle->numInts);
-    return Void();
-}
-
-Return<void> CrosGralloc3Mapper::lock(void* rawHandle, uint64_t cpuUsage, const Rect& accessRegion,
-                                      const hidl_handle& acquireFence, lock_cb hidlCb) {
-    if (!mDriver) {
-        drv_log("Failed to lock. Driver is uninitialized.\n");
-        hidlCb(Error::NO_RESOURCES, nullptr, 0, 0);
-        return Void();
-    }
-
-    buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle);
-    if (!bufferHandle) {
-        drv_log("Failed to lock. Empty handle.\n");
-        hidlCb(Error::BAD_BUFFER, nullptr, 0, 0);
-        return Void();
-    }
-
-    cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle);
-    if (crosHandle == nullptr) {
-        drv_log("Failed to lock. Invalid handle.\n");
-        hidlCb(Error::BAD_BUFFER, nullptr, 0, 0);
-        return Void();
-    }
-
-    LockResult result = lockInternal(crosHandle, cpuUsage, accessRegion, acquireFence);
-    if (result.error != Error::NONE) {
-        drv_log("Failed to lock. Failed to lockInternal.\n");
-        hidlCb(result.error, nullptr, 0, 0);
-        return Void();
-    }
-
-    int32_t bytesPerPixel = drv_bytes_per_pixel_from_format(crosHandle->format, 0);
-    int32_t bytesPerStride = static_cast<int32_t>(crosHandle->strides[0]);
-
-    hidlCb(Error::NONE, result.mapped[0], bytesPerPixel, bytesPerStride);
-    return Void();
-}
-
-Return<void> CrosGralloc3Mapper::lockYCbCr(void* rawHandle, uint64_t cpuUsage,
-                                           const Rect& accessRegion,
-                                           const android::hardware::hidl_handle& acquireFence,
-                                           lockYCbCr_cb hidlCb) {
-    YCbCrLayout ycbcr = {};
-
-    if (!mDriver) {
-        drv_log("Failed to lock. Driver is uninitialized.\n");
-        hidlCb(Error::NO_RESOURCES, ycbcr);
-        return Void();
-    }
-
-    buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle);
-    if (!bufferHandle) {
-        drv_log("Failed to lockYCbCr. Empty handle.\n");
-        hidlCb(Error::BAD_BUFFER, ycbcr);
-        return Void();
-    }
-
-    cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle);
-    if (crosHandle == nullptr) {
-        drv_log("Failed to lockYCbCr. Invalid handle.\n");
-        hidlCb(Error::BAD_BUFFER, ycbcr);
-        return Void();
-    }
-
-    LockResult result = lockInternal(crosHandle, cpuUsage, accessRegion, acquireFence);
-    if (result.error != Error::NONE) {
-        drv_log("Failed to lockYCbCr. Failed to lockInternal.\n");
-        hidlCb(result.error, ycbcr);
-        return Void();
-    }
-
-    switch (crosHandle->format) {
-        case DRM_FORMAT_NV12: {
-            ycbcr.y = result.mapped[0] + crosHandle->offsets[0];
-            ycbcr.cb = result.mapped[0] + crosHandle->offsets[1];
-            ycbcr.cr = result.mapped[0] + crosHandle->offsets[1] + 1;
-            ycbcr.yStride = crosHandle->strides[0];
-            ycbcr.cStride = crosHandle->strides[1];
-            ycbcr.chromaStep = 2;
-            break;
-        }
-        case DRM_FORMAT_NV21: {
-            ycbcr.y = result.mapped[0] + crosHandle->offsets[0];
-            ycbcr.cb = result.mapped[0] + crosHandle->offsets[1] + 1;
-            ycbcr.cr = result.mapped[0] + crosHandle->offsets[1];
-            ycbcr.yStride = crosHandle->strides[0];
-            ycbcr.cStride = crosHandle->strides[1];
-            ycbcr.chromaStep = 2;
-            break;
-        }
-        case DRM_FORMAT_YVU420: {
-            ycbcr.y = result.mapped[0] + crosHandle->offsets[0];
-            ycbcr.cb = result.mapped[0] + crosHandle->offsets[1];
-            ycbcr.cr = result.mapped[0] + crosHandle->offsets[2];
-            ycbcr.yStride = crosHandle->strides[0];
-            ycbcr.cStride = crosHandle->strides[1];
-            ycbcr.chromaStep = 1;
-            break;
-        }
-        case DRM_FORMAT_YVU420_ANDROID: {
-            ycbcr.y = result.mapped[0] + crosHandle->offsets[0];
-            ycbcr.cb = result.mapped[0] + crosHandle->offsets[2];
-            ycbcr.cr = result.mapped[0] + crosHandle->offsets[1];
-            ycbcr.yStride = crosHandle->strides[0];
-            ycbcr.cStride = crosHandle->strides[1];
-            ycbcr.chromaStep = 1;
-            break;
-        }
-        default: {
-            std::string format = get_drm_format_string(crosHandle->format);
-            drv_log("Failed to lockYCbCr. Unhandled format: %s\n", format.c_str());
-            hidlCb(Error::BAD_BUFFER, ycbcr);
-            return Void();
-        }
-    }
-
-    hidlCb(Error::NONE, ycbcr);
-    return Void();
-}
-
-CrosGralloc3Mapper::LockResult CrosGralloc3Mapper::lockInternal(
-        cros_gralloc_handle_t crosHandle, uint64_t cpuUsage, const Rect& region,
-        const android::hardware::hidl_handle& acquireFence) {
-    LockResult result = {};
-
-    if (!mDriver) {
-        drv_log("Failed to lock. Driver is uninitialized.\n");
-        result.error = Error::NO_RESOURCES;
-        return result;
-    }
-
-    if (cpuUsage == 0) {
-        drv_log("Failed to lock. Bad cpu usage: %" PRIu64 ".\n", cpuUsage);
-        result.error = Error::BAD_VALUE;
-        return result;
-    }
-
-    uint32_t mapUsage = 0;
-    int ret = convertToMapUsage(cpuUsage, &mapUsage);
-    if (ret) {
-        drv_log("Failed to lock. Convert usage failed.\n");
-        result.error = Error::BAD_VALUE;
-        return result;
-    }
-
-    if (region.left < 0) {
-        drv_log("Failed to lock. Invalid region: negative left value %d.\n", region.left);
-        result.error = Error::BAD_VALUE;
-        return result;
-    }
-
-    if (region.top < 0) {
-        drv_log("Failed to lock. Invalid region: negative top value %d.\n", region.top);
-        result.error = Error::BAD_VALUE;
-        return result;
-    }
-
-    if (region.width < 0) {
-        drv_log("Failed to lock. Invalid region: negative width value %d.\n", region.width);
-        result.error = Error::BAD_VALUE;
-        return result;
-    }
-
-    if (region.height < 0) {
-        drv_log("Failed to lock. Invalid region: negative height value %d.\n", region.height);
-        result.error = Error::BAD_VALUE;
-        return result;
-    }
-
-    if (region.width > crosHandle->width) {
-        drv_log("Failed to lock. Invalid region: width greater than buffer width (%d vs %d).\n",
-                region.width, crosHandle->width);
-        result.error = Error::BAD_VALUE;
-        return result;
-    }
-
-    if (region.height > crosHandle->height) {
-        drv_log("Failed to lock. Invalid region: height greater than buffer height (%d vs %d).\n",
-                region.height, crosHandle->height);
-        result.error = Error::BAD_VALUE;
-        return result;
-    }
-
-    struct rectangle rect = {static_cast<uint32_t>(region.left), static_cast<uint32_t>(region.top),
-                             static_cast<uint32_t>(region.width),
-                             static_cast<uint32_t>(region.height)};
-
-    // An access region of all zeros means the entire buffer.
-    if (rect.x == 0 && rect.y == 0 && rect.width == 0 && rect.height == 0) {
-        rect.width = crosHandle->width;
-        rect.height = crosHandle->height;
-    }
-
-    int acquireFenceFd = -1;
-    ret = convertToFenceFd(acquireFence, &acquireFenceFd);
-    if (ret) {
-        drv_log("Failed to lock. Bad acquire fence.\n");
-        result.error = Error::BAD_VALUE;
-        return result;
-    }
-
-    buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(crosHandle);
-    ret = mDriver->lock(bufferHandle, acquireFenceFd, false, &rect, mapUsage, result.mapped);
-    if (ret) {
-        result.error = Error::BAD_VALUE;
-        return result;
-    }
-
-    result.error = Error::NONE;
-    return result;
-}
-
-Return<void> CrosGralloc3Mapper::unlock(void* rawHandle, unlock_cb hidlCb) {
-    if (!mDriver) {
-        drv_log("Failed to unlock. Driver is uninitialized.\n");
-        hidlCb(Error::BAD_BUFFER, nullptr);
-        return Void();
-    }
-
-    buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle);
-    if (!bufferHandle) {
-        drv_log("Failed to unlock. Empty handle.\n");
-        hidlCb(Error::BAD_BUFFER, nullptr);
-        return Void();
-    }
-
-    int releaseFenceFd = -1;
-    int ret = mDriver->unlock(bufferHandle, &releaseFenceFd);
-    if (ret) {
-        drv_log("Failed to unlock.\n");
-        hidlCb(Error::BAD_BUFFER, nullptr);
-        return Void();
-    }
-
-    hidl_handle releaseFenceHandle;
-    ret = convertToFenceHandle(releaseFenceFd, &releaseFenceHandle);
-    if (ret) {
-        drv_log("Failed to unlock. Failed to convert release fence to handle.\n");
-        hidlCb(Error::BAD_BUFFER, nullptr);
-        return Void();
-    }
-
-    hidlCb(Error::NONE, releaseFenceHandle);
-    return Void();
-}
-
-Return<void> CrosGralloc3Mapper::isSupported(const BufferDescriptorInfo& descriptor,
-                                             isSupported_cb hidlCb) {
-    if (!mDriver) {
-        drv_log("Failed to isSupported. Driver is uninitialized.\n");
-        hidlCb(Error::BAD_VALUE, false);
-        return Void();
-    }
-
-    struct cros_gralloc_buffer_descriptor crosDescriptor;
-    if (convertToCrosDescriptor(descriptor, &crosDescriptor)) {
-        hidlCb(Error::NONE, false);
-        return Void();
-    }
-
-    bool supported = mDriver->is_supported(&crosDescriptor);
-    if (!supported) {
-        crosDescriptor.use_flags &= ~BO_USE_SCANOUT;
-        supported = mDriver->is_supported(&crosDescriptor);
-    }
-
-    hidlCb(Error::NONE, supported);
-    return Void();
-}
-
-int CrosGralloc3Mapper::getResolvedDrmFormat(PixelFormat pixelFormat, uint64_t bufferUsage,
-                                             uint32_t* outDrmFormat) {
-    uint32_t drmFormat;
-    if (convertToDrmFormat(pixelFormat, &drmFormat)) {
-        std::string pixelFormatString = getPixelFormatString(pixelFormat);
-        drv_log("Failed to getResolvedDrmFormat. Failed to convert format %s\n",
-                pixelFormatString.c_str());
-        return -EINVAL;
-    }
-
-    uint64_t usage;
-    if (convertToBufferUsage(bufferUsage, &usage)) {
-        std::string usageString = getUsageString(bufferUsage);
-        drv_log("Failed to getResolvedDrmFormat. Failed to convert usage %s\n",
-                usageString.c_str());
-        return -EINVAL;
-    }
-
-    uint32_t resolvedDrmFormat = mDriver->get_resolved_drm_format(drmFormat, usage);
-    if (resolvedDrmFormat == DRM_FORMAT_INVALID) {
-        std::string drmFormatString = get_drm_format_string(drmFormat);
-        drv_log("Failed to getResolvedDrmFormat. Failed to resolve drm format %s\n",
-                drmFormatString.c_str());
-        return -EINVAL;
-    }
-
-    *outDrmFormat = resolvedDrmFormat;
-
-    return 0;
-}
-
-android::hardware::graphics::mapper::V3_0::IMapper* HIDL_FETCH_IMapper(const char* /*name*/) {
-    return static_cast<android::hardware::graphics::mapper::V3_0::IMapper*>(new CrosGralloc3Mapper);
-}
diff --git a/cros_gralloc/gralloc3/CrosGralloc3Mapper.h b/cros_gralloc/gralloc3/CrosGralloc3Mapper.h
deleted file mode 100644
index 7ec92d5..0000000
--- a/cros_gralloc/gralloc3/CrosGralloc3Mapper.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2020 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include <android/hardware/graphics/mapper/3.0/IMapper.h>
-
-#include <optional>
-
-#include "cros_gralloc/cros_gralloc_driver.h"
-#include "cros_gralloc/cros_gralloc_handle.h"
-
-class CrosGralloc3Mapper : public android::hardware::graphics::mapper::V3_0::IMapper {
-  public:
-    CrosGralloc3Mapper();
-
-    android::hardware::Return<void> createDescriptor(const BufferDescriptorInfo& description,
-                                                     createDescriptor_cb hidlCb) override;
-
-    android::hardware::Return<void> importBuffer(const android::hardware::hidl_handle& rawHandle,
-                                                 importBuffer_cb hidlCb) override;
-
-    android::hardware::Return<android::hardware::graphics::mapper::V3_0::Error> freeBuffer(
-            void* rawHandle) override;
-
-    android::hardware::Return<android::hardware::graphics::mapper::V3_0::Error> validateBufferSize(
-            void* rawHandle, const BufferDescriptorInfo& descriptor, uint32_t stride) override;
-
-    android::hardware::Return<void> getTransportSize(void* rawHandle,
-                                                     getTransportSize_cb hidlCb) override;
-
-    android::hardware::Return<void> lock(void* rawHandle, uint64_t cpuUsage,
-                                         const Rect& accessRegion,
-                                         const android::hardware::hidl_handle& acquireFence,
-                                         lock_cb hidlCb) override;
-
-    android::hardware::Return<void> lockYCbCr(void* rawHandle, uint64_t cpuUsage,
-                                              const Rect& accessRegion,
-                                              const android::hardware::hidl_handle& acquireFence,
-                                              lockYCbCr_cb _hidl_cb) override;
-
-    android::hardware::Return<void> unlock(void* rawHandle, unlock_cb hidlCb) override;
-
-    android::hardware::Return<void> isSupported(const BufferDescriptorInfo& descriptor,
-                                                isSupported_cb hidlCb) override;
-
-  private:
-    int getResolvedDrmFormat(android::hardware::graphics::common::V1_2::PixelFormat pixelFormat,
-                             uint64_t bufferUsage, uint32_t* outDrmFormat);
-
-    struct LockResult {
-        android::hardware::graphics::mapper::V3_0::Error error;
-
-        uint8_t* mapped[DRV_MAX_PLANES];
-    };
-    LockResult lockInternal(cros_gralloc_handle_t crosHandle, uint64_t cpuUsage,
-                            const Rect& accessRegion,
-                            const android::hardware::hidl_handle& acquireFence);
-
-    std::unique_ptr<cros_gralloc_driver> mDriver;
-};
-
-extern "C" android::hardware::graphics::mapper::V3_0::IMapper* HIDL_FETCH_IMapper(const char* name);
diff --git a/cros_gralloc/gralloc3/CrosGralloc3Utils.cc b/cros_gralloc/gralloc3/CrosGralloc3Utils.cc
deleted file mode 100644
index 3f39305..0000000
--- a/cros_gralloc/gralloc3/CrosGralloc3Utils.cc
+++ /dev/null
@@ -1,402 +0,0 @@
-/*
- * Copyright 2020 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "cros_gralloc/gralloc3/CrosGralloc3Utils.h"
-
-#include <array>
-#include <limits>
-#include <unordered_map>
-
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <cutils/native_handle.h>
-
-#include "cros_gralloc/cros_gralloc_helpers.h"
-
-using android::hardware::hidl_bitfield;
-using android::hardware::hidl_handle;
-using android::hardware::hidl_vec;
-using android::hardware::graphics::common::V1_2::BufferUsage;
-using android::hardware::graphics::common::V1_2::PixelFormat;
-
-using BufferDescriptorInfo =
-        android::hardware::graphics::mapper::V3_0::IMapper::BufferDescriptorInfo;
-
-std::string getPixelFormatString(PixelFormat format) {
-    switch (format) {
-        case PixelFormat::BGRA_8888:
-            return "PixelFormat::BGRA_8888";
-        case PixelFormat::BLOB:
-            return "PixelFormat::BLOB";
-        case PixelFormat::DEPTH_16:
-            return "PixelFormat::DEPTH_16";
-        case PixelFormat::DEPTH_24:
-            return "PixelFormat::DEPTH_24";
-        case PixelFormat::DEPTH_24_STENCIL_8:
-            return "PixelFormat::DEPTH_24_STENCIL_8";
-        case PixelFormat::DEPTH_32F:
-            return "PixelFormat::DEPTH_24";
-        case PixelFormat::DEPTH_32F_STENCIL_8:
-            return "PixelFormat::DEPTH_24_STENCIL_8";
-        case PixelFormat::HSV_888:
-            return "PixelFormat::HSV_888";
-        case PixelFormat::IMPLEMENTATION_DEFINED:
-            return "PixelFormat::IMPLEMENTATION_DEFINED";
-        case PixelFormat::RAW10:
-            return "PixelFormat::RAW10";
-        case PixelFormat::RAW12:
-            return "PixelFormat::RAW12";
-        case PixelFormat::RAW16:
-            return "PixelFormat::RAW16";
-        case PixelFormat::RAW_OPAQUE:
-            return "PixelFormat::RAW_OPAQUE";
-        case PixelFormat::RGBA_1010102:
-            return "PixelFormat::RGBA_1010102";
-        case PixelFormat::RGBA_8888:
-            return "PixelFormat::RGBA_8888";
-        case PixelFormat::RGBA_FP16:
-            return "PixelFormat::RGBA_FP16";
-        case PixelFormat::RGBX_8888:
-            return "PixelFormat::RGBX_8888";
-        case PixelFormat::RGB_565:
-            return "PixelFormat::RGB_565";
-        case PixelFormat::RGB_888:
-            return "PixelFormat::RGB_888";
-        case PixelFormat::STENCIL_8:
-            return "PixelFormat::STENCIL_8";
-        case PixelFormat::Y16:
-            return "PixelFormat::Y16";
-        case PixelFormat::Y8:
-            return "PixelFormat::Y8";
-        case PixelFormat::YCBCR_420_888:
-            return "PixelFormat::YCBCR_420_888";
-        case PixelFormat::YCBCR_422_I:
-            return "PixelFormat::YCBCR_422_I";
-        case PixelFormat::YCBCR_422_SP:
-            return "PixelFormat::YCBCR_422_SP";
-        case PixelFormat::YCBCR_P010:
-            return "PixelFormat::YCBCR_P010";
-        case PixelFormat::YCRCB_420_SP:
-            return "PixelFormat::YCRCB_420_SP";
-        case PixelFormat::YV12:
-            return "PixelFormat::YV12";
-    }
-    return android::base::StringPrintf("PixelFormat::Unknown(%d)", static_cast<uint32_t>(format));
-}
-
-std::string getUsageString(hidl_bitfield<BufferUsage> bufferUsage) {
-    using Underlying = typename std::underlying_type<BufferUsage>::type;
-
-    Underlying usage = static_cast<Underlying>(bufferUsage);
-
-    std::vector<std::string> usages;
-    if (usage & BufferUsage::CAMERA_INPUT) {
-        usage &= ~static_cast<Underlying>(BufferUsage::CAMERA_INPUT);
-        usages.push_back("BufferUsage::CAMERA_INPUT");
-    }
-    if (usage & BufferUsage::CAMERA_OUTPUT) {
-        usage &= ~static_cast<Underlying>(BufferUsage::CAMERA_OUTPUT);
-        usages.push_back("BufferUsage::CAMERA_OUTPUT");
-    }
-    if (usage & BufferUsage::COMPOSER_CURSOR) {
-        usage &= ~static_cast<Underlying>(BufferUsage::COMPOSER_CURSOR);
-        usages.push_back("BufferUsage::COMPOSER_CURSOR");
-    }
-    if (usage & BufferUsage::COMPOSER_OVERLAY) {
-        usage &= ~static_cast<Underlying>(BufferUsage::COMPOSER_OVERLAY);
-        usages.push_back("BufferUsage::COMPOSER_OVERLAY");
-    }
-    if (usage & BufferUsage::CPU_READ_OFTEN) {
-        usage &= ~static_cast<Underlying>(BufferUsage::CPU_READ_OFTEN);
-        usages.push_back("BufferUsage::CPU_READ_OFTEN");
-    }
-    if (usage & BufferUsage::CPU_READ_NEVER) {
-        usage &= ~static_cast<Underlying>(BufferUsage::CPU_READ_NEVER);
-        usages.push_back("BufferUsage::CPU_READ_NEVER");
-    }
-    if (usage & BufferUsage::CPU_READ_RARELY) {
-        usage &= ~static_cast<Underlying>(BufferUsage::CPU_READ_RARELY);
-        usages.push_back("BufferUsage::CPU_READ_RARELY");
-    }
-    if (usage & BufferUsage::CPU_WRITE_NEVER) {
-        usage &= ~static_cast<Underlying>(BufferUsage::CPU_WRITE_NEVER);
-        usages.push_back("BufferUsage::CPU_WRITE_NEVER");
-    }
-    if (usage & BufferUsage::CPU_WRITE_OFTEN) {
-        usage &= ~static_cast<Underlying>(BufferUsage::CPU_WRITE_OFTEN);
-        usages.push_back("BufferUsage::CPU_WRITE_OFTEN");
-    }
-    if (usage & BufferUsage::CPU_WRITE_RARELY) {
-        usage &= ~static_cast<Underlying>(BufferUsage::CPU_WRITE_RARELY);
-        usages.push_back("BufferUsage::CPU_WRITE_RARELY");
-    }
-    if (usage & BufferUsage::GPU_RENDER_TARGET) {
-        usage &= ~static_cast<Underlying>(BufferUsage::GPU_RENDER_TARGET);
-        usages.push_back("BufferUsage::GPU_RENDER_TARGET");
-    }
-    if (usage & BufferUsage::GPU_TEXTURE) {
-        usage &= ~static_cast<Underlying>(BufferUsage::GPU_TEXTURE);
-        usages.push_back("BufferUsage::GPU_TEXTURE");
-    }
-    if (usage & BufferUsage::PROTECTED) {
-        usage &= ~static_cast<Underlying>(BufferUsage::PROTECTED);
-        usages.push_back("BufferUsage::PROTECTED");
-    }
-    if (usage & BufferUsage::RENDERSCRIPT) {
-        usage &= ~static_cast<Underlying>(BufferUsage::RENDERSCRIPT);
-        usages.push_back("BufferUsage::RENDERSCRIPT");
-    }
-    if (usage & BufferUsage::VIDEO_DECODER) {
-        usage &= ~static_cast<Underlying>(BufferUsage::VIDEO_DECODER);
-        usages.push_back("BufferUsage::VIDEO_DECODER");
-    }
-    if (usage & BufferUsage::VIDEO_ENCODER) {
-        usage &= ~static_cast<Underlying>(BufferUsage::VIDEO_ENCODER);
-        usages.push_back("BufferUsage::VIDEO_ENCODER");
-    }
-
-    if (usage) {
-        usages.push_back(android::base::StringPrintf("UnknownUsageBits-%" PRIu64, usage));
-    }
-
-    return android::base::Join(usages, '|');
-}
-
-int convertToDrmFormat(PixelFormat format, uint32_t* outDrmFormat) {
-    switch (format) {
-        case PixelFormat::BGRA_8888:
-            *outDrmFormat = DRM_FORMAT_ARGB8888;
-            return 0;
-        /**
-         * Choose DRM_FORMAT_R8 because <system/graphics.h> requires the buffers
-         * with a format HAL_PIXEL_FORMAT_BLOB have a height of 1, and width
-         * equal to their size in bytes.
-         */
-        case PixelFormat::BLOB:
-            *outDrmFormat = DRM_FORMAT_R8;
-            return 0;
-        case PixelFormat::DEPTH_16:
-            return -EINVAL;
-        case PixelFormat::DEPTH_24:
-            return -EINVAL;
-        case PixelFormat::DEPTH_24_STENCIL_8:
-            return -EINVAL;
-        case PixelFormat::DEPTH_32F:
-            return -EINVAL;
-        case PixelFormat::DEPTH_32F_STENCIL_8:
-            return -EINVAL;
-        case PixelFormat::HSV_888:
-            return -EINVAL;
-        case PixelFormat::IMPLEMENTATION_DEFINED:
-            *outDrmFormat = DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED;
-            return 0;
-        case PixelFormat::RAW10:
-            return -EINVAL;
-        case PixelFormat::RAW12:
-            return -EINVAL;
-        case PixelFormat::RAW16:
-            *outDrmFormat = DRM_FORMAT_R16;
-            return 0;
-        /* TODO use blob */
-        case PixelFormat::RAW_OPAQUE:
-            return -EINVAL;
-        case PixelFormat::RGBA_1010102:
-            *outDrmFormat = DRM_FORMAT_ABGR2101010;
-            return 0;
-        case PixelFormat::RGBA_8888:
-            *outDrmFormat = DRM_FORMAT_ABGR8888;
-            return 0;
-        case PixelFormat::RGBA_FP16:
-            *outDrmFormat = DRM_FORMAT_ABGR16161616F;
-            return 0;
-        case PixelFormat::RGBX_8888:
-            *outDrmFormat = DRM_FORMAT_XBGR8888;
-            return 0;
-        case PixelFormat::RGB_565:
-            *outDrmFormat = DRM_FORMAT_RGB565;
-            return 0;
-        case PixelFormat::RGB_888:
-            *outDrmFormat = DRM_FORMAT_RGB888;
-            return 0;
-        case PixelFormat::STENCIL_8:
-            return -EINVAL;
-        case PixelFormat::Y16:
-            *outDrmFormat = DRM_FORMAT_R16;
-            return 0;
-        case PixelFormat::Y8:
-            *outDrmFormat = DRM_FORMAT_R8;
-            return 0;
-        case PixelFormat::YCBCR_420_888:
-            *outDrmFormat = DRM_FORMAT_FLEX_YCbCr_420_888;
-            return 0;
-        case PixelFormat::YCBCR_422_SP:
-            return -EINVAL;
-        case PixelFormat::YCBCR_422_I:
-            return -EINVAL;
-        case PixelFormat::YCBCR_P010:
-            *outDrmFormat = DRM_FORMAT_P010;
-            return 0;
-        case PixelFormat::YCRCB_420_SP:
-            *outDrmFormat = DRM_FORMAT_NV21;
-            return 0;
-        case PixelFormat::YV12:
-            *outDrmFormat = DRM_FORMAT_YVU420_ANDROID;
-            return 0;
-    };
-    return -EINVAL;
-}
-
-int convertToBufferUsage(uint64_t grallocUsage, uint64_t* outBufferUsage) {
-    uint64_t bufferUsage = BO_USE_NONE;
-
-    if ((grallocUsage & BufferUsage::CPU_READ_MASK) ==
-        static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY)) {
-        bufferUsage |= BO_USE_SW_READ_RARELY;
-    }
-    if ((grallocUsage & BufferUsage::CPU_READ_MASK) ==
-        static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN)) {
-        bufferUsage |= BO_USE_SW_READ_OFTEN;
-    }
-    if ((grallocUsage & BufferUsage::CPU_WRITE_MASK) ==
-        static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY)) {
-        bufferUsage |= BO_USE_SW_WRITE_RARELY;
-    }
-    if ((grallocUsage & BufferUsage::CPU_WRITE_MASK) ==
-        static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN)) {
-        bufferUsage |= BO_USE_SW_WRITE_OFTEN;
-    }
-    if (grallocUsage & BufferUsage::GPU_TEXTURE) {
-        bufferUsage |= BO_USE_TEXTURE;
-    }
-    if (grallocUsage & BufferUsage::GPU_RENDER_TARGET) {
-        bufferUsage |= BO_USE_RENDERING;
-    }
-    if (grallocUsage & BufferUsage::COMPOSER_OVERLAY) {
-        /* HWC wants to use display hardware, but can defer to OpenGL. */
-        bufferUsage |= BO_USE_SCANOUT | BO_USE_TEXTURE;
-    }
-    /* Map this flag to linear until real HW protection is available on Android. */
-    if (grallocUsage & BufferUsage::PROTECTED) {
-        bufferUsage |= BO_USE_LINEAR;
-    }
-    if (grallocUsage & BufferUsage::COMPOSER_CURSOR) {
-        bufferUsage |= BO_USE_NONE;
-    }
-    if (grallocUsage & BufferUsage::VIDEO_ENCODER) {
-        /*HACK: See b/30054495 */
-        bufferUsage |= BO_USE_SW_READ_OFTEN;
-    }
-    if (grallocUsage & BufferUsage::CAMERA_OUTPUT) {
-        bufferUsage |= BO_USE_CAMERA_WRITE;
-    }
-    if (grallocUsage & BufferUsage::CAMERA_INPUT) {
-        bufferUsage |= BO_USE_CAMERA_READ;
-    }
-    if (grallocUsage & BufferUsage::RENDERSCRIPT) {
-        bufferUsage |= BO_USE_RENDERSCRIPT;
-    }
-    if (grallocUsage & BufferUsage::VIDEO_DECODER) {
-        bufferUsage |= BO_USE_HW_VIDEO_DECODER;
-    }
-
-    *outBufferUsage = bufferUsage;
-    return 0;
-}
-
-int convertToMapUsage(uint64_t grallocUsage, uint32_t* outMapUsage) {
-    uint32_t mapUsage = BO_MAP_NONE;
-
-    if (grallocUsage & BufferUsage::CPU_READ_MASK) {
-        mapUsage |= BO_MAP_READ;
-    }
-    if (grallocUsage & BufferUsage::CPU_WRITE_MASK) {
-        mapUsage |= BO_MAP_WRITE;
-    }
-
-    *outMapUsage = mapUsage;
-    return 0;
-}
-
-int convertToCrosDescriptor(const BufferDescriptorInfo& descriptor,
-                            struct cros_gralloc_buffer_descriptor* outCrosDescriptor) {
-    outCrosDescriptor->width = descriptor.width;
-    outCrosDescriptor->height = descriptor.height;
-    outCrosDescriptor->droid_format = static_cast<int32_t>(descriptor.format);
-    outCrosDescriptor->droid_usage = descriptor.usage;
-    outCrosDescriptor->reserved_region_size = 0;
-    if (descriptor.layerCount > 1) {
-        drv_log("Failed to convert descriptor. Unsupported layerCount: %d\n",
-                descriptor.layerCount);
-        return -EINVAL;
-    }
-    if (convertToDrmFormat(descriptor.format, &outCrosDescriptor->drm_format)) {
-        std::string pixelFormatString = getPixelFormatString(descriptor.format);
-        drv_log("Failed to convert descriptor. Unsupported format %s\n", pixelFormatString.c_str());
-        return -EINVAL;
-    }
-    if (convertToBufferUsage(descriptor.usage, &outCrosDescriptor->use_flags)) {
-        std::string usageString = getUsageString(descriptor.usage);
-        drv_log("Failed to convert descriptor. Unsupported usage flags %s\n", usageString.c_str());
-        return -EINVAL;
-    }
-    return 0;
-}
-
-int convertToFenceFd(const hidl_handle& fenceHandle, int* outFenceFd) {
-    if (!outFenceFd) {
-        return -EINVAL;
-    }
-
-    const native_handle_t* nativeHandle = fenceHandle.getNativeHandle();
-    if (nativeHandle && nativeHandle->numFds > 1) {
-        return -EINVAL;
-    }
-
-    *outFenceFd = (nativeHandle && nativeHandle->numFds == 1) ? nativeHandle->data[0] : -1;
-    return 0;
-}
-
-int convertToFenceHandle(int fenceFd, hidl_handle* outFenceHandle) {
-    if (!outFenceHandle) {
-        return -EINVAL;
-    }
-    if (fenceFd < 0) {
-        return 0;
-    }
-
-    NATIVE_HANDLE_DECLARE_STORAGE(handleStorage, 1, 0);
-    auto fenceHandle = native_handle_init(handleStorage, 1, 0);
-    fenceHandle->data[0] = fenceFd;
-
-    *outFenceHandle = fenceHandle;
-    return 0;
-}
-
-std::optional<BufferDescriptorInfo> decodeBufferDescriptorInfo(const hidl_vec<uint32_t>& encoded) {
-    if (encoded.size() != 5) {
-        drv_log("Failed to decodeBufferDescriptorInfo. Invalid size: %zd.\n", encoded.size());
-        return {};
-    }
-
-    BufferDescriptorInfo descriptor;
-    descriptor.width = encoded[0];
-    descriptor.height = encoded[1];
-    descriptor.layerCount = encoded[2];
-    descriptor.format = static_cast<PixelFormat>(encoded[3]);
-    descriptor.usage = encoded[4];
-    return std::move(descriptor);
-}
-
-std::optional<hidl_vec<uint32_t>> encodeBufferDescriptorInfo(const BufferDescriptorInfo& info) {
-    hidl_vec<uint32_t> encoded;
-    encoded.resize(5);
-    encoded[0] = info.width;
-    encoded[1] = info.height;
-    encoded[2] = info.layerCount;
-    encoded[3] = static_cast<uint32_t>(info.format);
-    encoded[4] = info.usage & std::numeric_limits<uint32_t>::max();
-    return std::move(encoded);
-}
diff --git a/cros_gralloc/gralloc3/CrosGralloc3Utils.h b/cros_gralloc/gralloc3/CrosGralloc3Utils.h
deleted file mode 100644
index 0492568..0000000
--- a/cros_gralloc/gralloc3/CrosGralloc3Utils.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2020 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include <optional>
-#include <string>
-#include <vector>
-
-#include <android/hardware/graphics/common/1.2/types.h>
-#include <android/hardware/graphics/mapper/3.0/IMapper.h>
-
-std::string getPixelFormatString(android::hardware::graphics::common::V1_2::PixelFormat format);
-
-std::string getUsageString(
-        android::hardware::hidl_bitfield<android::hardware::graphics::common::V1_2::BufferUsage>
-                usage);
-
-int convertToDrmFormat(android::hardware::graphics::common::V1_2::PixelFormat format,
-                       uint32_t* outDrmFormat);
-
-int convertToBufferUsage(uint64_t grallocUsage, uint64_t* outBufferUsage);
-
-int convertToMapUsage(uint64_t grallocUsage, uint32_t* outMapUsage);
-
-int convertToCrosDescriptor(
-        const android::hardware::graphics::mapper::V3_0::IMapper::BufferDescriptorInfo& descriptor,
-        struct cros_gralloc_buffer_descriptor* outCrosDescriptor);
-
-int convertToFenceFd(const android::hardware::hidl_handle& fence_handle, int* out_fence_fd);
-
-int convertToFenceHandle(int fence_fd, android::hardware::hidl_handle* out_fence_handle);
-
-std::optional<android::hardware::graphics::mapper::V3_0::IMapper::BufferDescriptorInfo>
-decodeBufferDescriptorInfo(const android::hardware::hidl_vec<uint32_t>& encoded);
-
-std::optional<android::hardware::hidl_vec<uint32_t>> encodeBufferDescriptorInfo(
-        const android::hardware::graphics::mapper::V3_0::IMapper::BufferDescriptorInfo& info);
diff --git a/cros_gralloc/gralloc3/android.hardware.graphics.allocator@3.0-service.minigbm.rc b/cros_gralloc/gralloc3/android.hardware.graphics.allocator@3.0-service.minigbm.rc
deleted file mode 100644
index 7377cee..0000000
--- a/cros_gralloc/gralloc3/android.hardware.graphics.allocator@3.0-service.minigbm.rc
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Copyright 2020 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-#
-
-service vendor.graphics.allocator-3-0 /vendor/bin/hw/android.hardware.graphics.allocator@3.0-service.minigbm
-    interface android.hardware.graphics.allocator@3.0::IAllocator default
-    class hal animation
-    user system
-    group graphics drmrpc
-    capabilities SYS_NICE
-    onrestart restart surfaceflinger
-    writepid /dev/cpuset/system-background/tasks
diff --git a/cros_gralloc/gralloc4/Android.bp b/cros_gralloc/gralloc4/Android.bp
index 4d2b542..a0a8622 100644
--- a/cros_gralloc/gralloc4/Android.bp
+++ b/cros_gralloc/gralloc4/Android.bp
@@ -1,34 +1,24 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "external_minigbm_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    //   SPDX-license-identifier-BSD
-    default_applicable_licenses: ["external_minigbm_license"],
-}
-
-cc_defaults {
-    name: "service_minigbm_defaults",
+cc_binary {
+    name: "android.hardware.graphics.allocator@4.0-service.minigbm",
     relative_install_path: "hw",
     vendor: true,
-
-    vintf_fragments: ["android.hardware.graphics.allocator@4.0.xml"],
+    init_rc: ["android.hardware.graphics.allocator@4.0-service.minigbm.rc"],
 
     cflags: [
         "-Wall",
@@ -49,6 +39,7 @@
 
     static_libs: [
         "libdrm",
+        "libminigbm_cros_gralloc",
     ],
 
     srcs: [
@@ -58,31 +49,11 @@
     ],
 }
 
-cc_binary {
-    name: "android.hardware.graphics.allocator@4.0-service.minigbm",
-    init_rc: ["android.hardware.graphics.allocator@4.0-service.minigbm.rc"],
-    defaults: ["service_minigbm_defaults"],
-    static_libs: [
-        "libminigbm_cros_gralloc",
-    ],
-}
-
-cc_binary {
-    name: "android.hardware.graphics.allocator@4.0-service.minigbm_msm",
-    init_rc: ["android.hardware.graphics.allocator@4.0-service.minigbm_msm.rc"],
-    defaults: ["service_minigbm_defaults"],
-    static_libs: [
-        "libminigbm_cros_gralloc_msm",
-    ],
-}
-
-cc_defaults {
-    name: "impl_minigbm_defaults",
+cc_library_shared {
+    name: "android.hardware.graphics.mapper@4.0-impl.minigbm",
     relative_install_path: "hw",
     vendor: true,
 
-    vintf_fragments: ["android.hardware.graphics.mapper@4.0.xml"],
-
     cflags: [
         "-Wall",
         "-Werror",
@@ -101,6 +72,7 @@
 
     static_libs: [
         "libdrm",
+        "libminigbm_cros_gralloc",
     ],
 
     srcs: [
@@ -108,23 +80,3 @@
         "CrosGralloc4Utils.cc",
     ],
 }
-
-cc_library_shared {
-    name: "android.hardware.graphics.mapper@4.0-impl.minigbm",
-    defaults: ["impl_minigbm_defaults"],
-
-    static_libs: [
-        "libminigbm_cros_gralloc",
-    ],
-
-}
-
-cc_library_shared {
-    name: "android.hardware.graphics.mapper@4.0-impl.minigbm_msm",
-    defaults: ["impl_minigbm_defaults"],
-
-    static_libs: [
-        "libminigbm_cros_gralloc_msm",
-    ],
-
-}
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc b/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc
index e7e5f3a..4fb7845 100644
--- a/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc
+++ b/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc
@@ -53,7 +53,7 @@
     }
 
     if (!supported) {
-        std::string drmFormatString = get_drm_format_string(crosDescriptor.drm_format);
+        std::string drmFormatString = getDrmFormatString(crosDescriptor.drm_format);
         std::string pixelFormatString = getPixelFormatString(descriptor.format);
         std::string usageString = getUsageString(descriptor.usage);
         drv_log("Unsupported combination -- pixel format: %s, drm format:%s, usage: %s\n",
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc b/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc
index 1bfd442..47e24ac 100644
--- a/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc
+++ b/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc
@@ -13,9 +13,7 @@
 #include <cutils/native_handle.h>
 #include <gralloctypes/Gralloc4.h>
 
-#include "cros_gralloc/cros_gralloc_helpers.h"
 #include "cros_gralloc/gralloc4/CrosGralloc4Utils.h"
-
 #include "helpers.h"
 
 using aidl::android::hardware::graphics::common::BlendMode;
@@ -31,60 +29,11 @@
 using android::hardware::graphics::mapper::V4_0::Error;
 using android::hardware::graphics::mapper::V4_0::IMapper;
 
-namespace {
-
-// Provides a single instance of cros_gralloc_driver to all active instances of
-// CrosGralloc4Mapper in a single process while destroying the cros_gralloc_driver
-// when there are no active instances of CrosGralloc4Mapper.
-class DriverProvider {
-  public:
-    static DriverProvider* Get() {
-        static DriverProvider* instance = new DriverProvider();
-        return instance;
+CrosGralloc4Mapper::CrosGralloc4Mapper() : mDriver(std::make_unique<cros_gralloc_driver>()) {
+    if (mDriver->init()) {
+        drv_log("Failed to initialize driver.\n");
+        mDriver = nullptr;
     }
-
-    cros_gralloc_driver* GetAndReferenceDriver() {
-        std::lock_guard<std::mutex> lock(mMutex);
-        if (!mDriver) {
-            mDriver = std::make_unique<cros_gralloc_driver>();
-            if (mDriver->init()) {
-                drv_log("Failed to initialize driver.\n");
-                mDriver.reset();
-                return nullptr;
-            }
-        }
-
-        ++mReferenceCount;
-        return mDriver.get();
-    }
-
-    void UnreferenceDriver() {
-        std::lock_guard<std::mutex> lock(mMutex);
-
-        --mReferenceCount;
-
-        if (mReferenceCount == 0) {
-            mDriver.reset();
-        }
-    }
-
-  private:
-    DriverProvider() = default;
-
-    std::mutex mMutex;
-    std::unique_ptr<cros_gralloc_driver> mDriver;
-    std::size_t mReferenceCount = 0;
-};
-
-}  // namespace
-
-CrosGralloc4Mapper::CrosGralloc4Mapper() {
-    mDriver = DriverProvider::Get()->GetAndReferenceDriver();
-}
-
-CrosGralloc4Mapper::~CrosGralloc4Mapper() {
-    mDriver = nullptr;
-    DriverProvider::Get()->UnreferenceDriver();
 }
 
 Return<void> CrosGralloc4Mapper::createDescriptor(const BufferDescriptorInfo& description,
@@ -136,7 +85,7 @@
 
     native_handle_t* importedBufferHandle = native_handle_clone(bufferHandle);
     if (!importedBufferHandle) {
-        drv_log("Failed to importBuffer. Handle clone failed: %s.\n", strerror(errno));
+        drv_log("Failed to importBuffer. Handle clone failed.\n");
         hidlCb(Error::NO_RESOURCES, nullptr);
         return Void();
     }
@@ -506,7 +455,7 @@
     if (metadataType == android::gralloc4::MetadataType_BufferId) {
         status = android::gralloc4::encodeBufferId(crosHandle->id, &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_Name) {
-        const char* name = (const char*)(&crosHandle->data[crosHandle->name_offset]);
+        const char* name = (const char*)(&crosHandle->base.data[crosHandle->name_offset]);
         status = android::gralloc4::encodeName(name, &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_Width) {
         status = android::gralloc4::encodeWidth(crosHandle->width, &encodedMetadata);
@@ -518,8 +467,7 @@
         PixelFormat pixelFormat = static_cast<PixelFormat>(crosHandle->droid_format);
         status = android::gralloc4::encodePixelFormatRequested(pixelFormat, &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_PixelFormatFourCC) {
-        status = android::gralloc4::encodePixelFormatFourCC(
-                drv_get_standard_fourcc(crosHandle->format), &encodedMetadata);
+        status = android::gralloc4::encodePixelFormatFourCC(crosHandle->format, &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_PixelFormatModifier) {
         status = android::gralloc4::encodePixelFormatModifier(crosHandle->format_modifier,
                                                               &encodedMetadata);
@@ -549,8 +497,8 @@
             planeLayout.offsetInBytes = crosHandle->offsets[plane];
             planeLayout.strideInBytes = crosHandle->strides[plane];
             planeLayout.totalSizeInBytes = crosHandle->sizes[plane];
-            planeLayout.widthInSamples = crosHandle->width / planeLayout.horizontalSubsampling;
-            planeLayout.heightInSamples = crosHandle->height / planeLayout.verticalSubsampling;
+            planeLayout.widthInSamples = crosHandle->width;
+            planeLayout.heightInSamples = crosHandle->height;
         }
 
         status = android::gralloc4::encodePlaneLayouts(planeLayouts, &encodedMetadata);
@@ -636,7 +584,7 @@
         std::string pixelFormatString = getPixelFormatString(pixelFormat);
         drv_log("Failed to getResolvedDrmFormat. Failed to convert format %s\n",
                 pixelFormatString.c_str());
-        return -EINVAL;
+        return -1;
     }
 
     uint64_t usage;
@@ -644,15 +592,15 @@
         std::string usageString = getUsageString(bufferUsage);
         drv_log("Failed to getResolvedDrmFormat. Failed to convert usage %s\n",
                 usageString.c_str());
-        return -EINVAL;
+        return -1;
     }
 
     uint32_t resolvedDrmFormat = mDriver->get_resolved_drm_format(drmFormat, usage);
     if (resolvedDrmFormat == DRM_FORMAT_INVALID) {
-        std::string drmFormatString = get_drm_format_string(drmFormat);
+        std::string drmFormatString = getDrmFormatString(drmFormat);
         drv_log("Failed to getResolvedDrmFormat. Failed to resolve drm format %s\n",
                 drmFormatString.c_str());
-        return -EINVAL;
+        return -1;
     }
 
     *outDrmFormat = resolvedDrmFormat;
@@ -688,8 +636,7 @@
             hidlCb(Error::BAD_VALUE, encodedMetadata);
             return Void();
         }
-        status = android::gralloc4::encodePixelFormatFourCC(drv_get_standard_fourcc(drmFormat),
-                                                            &encodedMetadata);
+        status = android::gralloc4::encodePixelFormatFourCC(drmFormat, &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_Usage) {
         status = android::gralloc4::encodeUsage(descriptor.usage, &encodedMetadata);
     } else if (metadataType == android::gralloc4::MetadataType_ProtectedContent) {
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Mapper.h b/cros_gralloc/gralloc4/CrosGralloc4Mapper.h
index 3c159a2..b318930 100644
--- a/cros_gralloc/gralloc4/CrosGralloc4Mapper.h
+++ b/cros_gralloc/gralloc4/CrosGralloc4Mapper.h
@@ -12,7 +12,6 @@
 class CrosGralloc4Mapper : public android::hardware::graphics::mapper::V4_0::IMapper {
   public:
     CrosGralloc4Mapper();
-    ~CrosGralloc4Mapper();
 
     android::hardware::Return<void> createDescriptor(const BufferDescriptorInfo& description,
                                                      createDescriptor_cb hidlCb) override;
@@ -75,7 +74,7 @@
     int getResolvedDrmFormat(android::hardware::graphics::common::V1_2::PixelFormat pixelFormat,
                              uint64_t bufferUsage, uint32_t* outDrmFormat);
 
-    cros_gralloc_driver* mDriver = nullptr;
+    std::unique_ptr<cros_gralloc_driver> mDriver;
 };
 
 extern "C" android::hardware::graphics::mapper::V4_0::IMapper* HIDL_FETCH_IMapper(const char* name);
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Utils.cc b/cros_gralloc/gralloc4/CrosGralloc4Utils.cc
index 9bc27cb..8931164 100644
--- a/cros_gralloc/gralloc4/CrosGralloc4Utils.cc
+++ b/cros_gralloc/gralloc4/CrosGralloc4Utils.cc
@@ -29,6 +29,112 @@
 using BufferDescriptorInfo =
         android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo;
 
+std::string getDrmFormatString(uint32_t drmFormat) {
+    switch (drmFormat) {
+        case DRM_FORMAT_ABGR1555:
+            return "DRM_FORMAT_ABGR1555";
+        case DRM_FORMAT_ABGR2101010:
+            return "DRM_FORMAT_ABGR2101010";
+        case DRM_FORMAT_ABGR4444:
+            return "DRM_FORMAT_ABGR4444";
+        case DRM_FORMAT_ABGR8888:
+            return "DRM_FORMAT_ABGR8888";
+        case DRM_FORMAT_ARGB1555:
+            return "DRM_FORMAT_ARGB1555";
+        case DRM_FORMAT_ARGB2101010:
+            return "DRM_FORMAT_ARGB2101010";
+        case DRM_FORMAT_ARGB4444:
+            return "DRM_FORMAT_ARGB4444";
+        case DRM_FORMAT_ARGB8888:
+            return "DRM_FORMAT_ARGB8888";
+        case DRM_FORMAT_AYUV:
+            return "DRM_FORMAT_AYUV";
+        case DRM_FORMAT_BGR233:
+            return "DRM_FORMAT_BGR233";
+        case DRM_FORMAT_BGR565:
+            return "DRM_FORMAT_BGR565";
+        case DRM_FORMAT_BGR888:
+            return "DRM_FORMAT_BGR888";
+        case DRM_FORMAT_BGRA1010102:
+            return "DRM_FORMAT_BGRA1010102";
+        case DRM_FORMAT_BGRA4444:
+            return "DRM_FORMAT_BGRA4444";
+        case DRM_FORMAT_BGRA5551:
+            return "DRM_FORMAT_BGRA5551";
+        case DRM_FORMAT_BGRA8888:
+            return "DRM_FORMAT_BGRA8888";
+        case DRM_FORMAT_BGRX1010102:
+            return "DRM_FORMAT_BGRX1010102";
+        case DRM_FORMAT_BGRX4444:
+            return "DRM_FORMAT_BGRX4444";
+        case DRM_FORMAT_BGRX5551:
+            return "DRM_FORMAT_BGRX5551";
+        case DRM_FORMAT_BGRX8888:
+            return "DRM_FORMAT_BGRX8888";
+        case DRM_FORMAT_C8:
+            return "DRM_FORMAT_C8";
+        case DRM_FORMAT_GR88:
+            return "DRM_FORMAT_GR88";
+        case DRM_FORMAT_NV12:
+            return "DRM_FORMAT_NV12";
+        case DRM_FORMAT_NV21:
+            return "DRM_FORMAT_NV21";
+        case DRM_FORMAT_R8:
+            return "DRM_FORMAT_R8";
+        case DRM_FORMAT_RG88:
+            return "DRM_FORMAT_RG88";
+        case DRM_FORMAT_RGB332:
+            return "DRM_FORMAT_RGB332";
+        case DRM_FORMAT_RGB565:
+            return "DRM_FORMAT_RGB565";
+        case DRM_FORMAT_RGB888:
+            return "DRM_FORMAT_RGB888";
+        case DRM_FORMAT_RGBA1010102:
+            return "DRM_FORMAT_RGBA1010102";
+        case DRM_FORMAT_RGBA4444:
+            return "DRM_FORMAT_RGBA4444";
+        case DRM_FORMAT_RGBA5551:
+            return "DRM_FORMAT_RGBA5551";
+        case DRM_FORMAT_RGBA8888:
+            return "DRM_FORMAT_RGBA8888";
+        case DRM_FORMAT_RGBX1010102:
+            return "DRM_FORMAT_RGBX1010102";
+        case DRM_FORMAT_RGBX4444:
+            return "DRM_FORMAT_RGBX4444";
+        case DRM_FORMAT_RGBX5551:
+            return "DRM_FORMAT_RGBX5551";
+        case DRM_FORMAT_RGBX8888:
+            return "DRM_FORMAT_RGBX8888";
+        case DRM_FORMAT_UYVY:
+            return "DRM_FORMAT_UYVY";
+        case DRM_FORMAT_VYUY:
+            return "DRM_FORMAT_VYUY";
+        case DRM_FORMAT_XBGR1555:
+            return "DRM_FORMAT_XBGR1555";
+        case DRM_FORMAT_XBGR2101010:
+            return "DRM_FORMAT_XBGR2101010";
+        case DRM_FORMAT_XBGR4444:
+            return "DRM_FORMAT_XBGR4444";
+        case DRM_FORMAT_XBGR8888:
+            return "DRM_FORMAT_XBGR8888";
+        case DRM_FORMAT_XRGB1555:
+            return "DRM_FORMAT_XRGB1555";
+        case DRM_FORMAT_XRGB2101010:
+            return "DRM_FORMAT_XRGB2101010";
+        case DRM_FORMAT_XRGB4444:
+            return "DRM_FORMAT_XRGB4444";
+        case DRM_FORMAT_XRGB8888:
+            return "DRM_FORMAT_XRGB8888";
+        case DRM_FORMAT_YUYV:
+            return "DRM_FORMAT_YUYV";
+        case DRM_FORMAT_YVU420:
+            return "DRM_FORMAT_YVU420";
+        case DRM_FORMAT_YVYU:
+            return "DRM_FORMAT_YVYU";
+    }
+    return android::base::StringPrintf("Unknown(%d)", drmFormat);
+}
+
 std::string getPixelFormatString(PixelFormat format) {
     switch (format) {
         case PixelFormat::BGRA_8888:
@@ -282,9 +388,8 @@
         /* HWC wants to use display hardware, but can defer to OpenGL. */
         bufferUsage |= BO_USE_SCANOUT | BO_USE_TEXTURE;
     }
-    /* Map this flag to linear until real HW protection is available on Android. */
     if (grallocUsage & BufferUsage::PROTECTED) {
-        bufferUsage |= BO_USE_LINEAR;
+        bufferUsage |= BO_USE_PROTECTED;
     }
     if (grallocUsage & BufferUsage::COMPOSER_CURSOR) {
         bufferUsage |= BO_USE_NONE;
@@ -318,20 +423,16 @@
     outCrosDescriptor->droid_format = static_cast<int32_t>(descriptor.format);
     outCrosDescriptor->droid_usage = descriptor.usage;
     outCrosDescriptor->reserved_region_size = descriptor.reservedSize;
-    if (descriptor.layerCount > 1) {
-        drv_log("Failed to convert descriptor. Unsupported layerCount: %d\n",
-                descriptor.layerCount);
-        return -EINVAL;
-    }
+
     if (convertToDrmFormat(descriptor.format, &outCrosDescriptor->drm_format)) {
         std::string pixelFormatString = getPixelFormatString(descriptor.format);
-        drv_log("Failed to convert descriptor. Unsupported format %s\n", pixelFormatString.c_str());
-        return -EINVAL;
+        drv_log("Failed to convert descriptor. Unsupported fomat %s\n", pixelFormatString.c_str());
+        return -1;
     }
     if (convertToBufferUsage(descriptor.usage, &outCrosDescriptor->use_flags)) {
         std::string usageString = getUsageString(descriptor.usage);
         drv_log("Failed to convert descriptor. Unsupported usage flags %s\n", usageString.c_str());
-        return -EINVAL;
+        return -1;
     }
     return 0;
 }
@@ -663,9 +764,9 @@
     const auto it = planeLayoutsMap.find(drmFormat);
     if (it == planeLayoutsMap.end()) {
         drv_log("Unknown plane layout for format %d\n", drmFormat);
-        return -EINVAL;
+        return -1;
     }
 
     *outPlaneLayouts = it->second;
     return 0;
-}
+}
\ No newline at end of file
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Utils.h b/cros_gralloc/gralloc4/CrosGralloc4Utils.h
index 370922c..094ef74 100644
--- a/cros_gralloc/gralloc4/CrosGralloc4Utils.h
+++ b/cros_gralloc/gralloc4/CrosGralloc4Utils.h
@@ -13,6 +13,8 @@
 
 #include "cros_gralloc/cros_gralloc_types.h"
 
+std::string getDrmFormatString(uint32_t drmFormat);
+
 std::string getPixelFormatString(android::hardware::graphics::common::V1_2::PixelFormat format);
 
 std::string getUsageString(
@@ -36,4 +38,4 @@
 
 int getPlaneLayouts(
         uint32_t drm_format,
-        std::vector<aidl::android::hardware::graphics::common::PlaneLayout>* out_layouts);
+        std::vector<aidl::android::hardware::graphics::common::PlaneLayout>* out_layouts);
\ No newline at end of file
diff --git a/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm_msm.rc b/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm_msm.rc
deleted file mode 100644
index dceb747..0000000
--- a/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm_msm.rc
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Copyright 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-service vendor.graphics.allocator-4-0 /vendor/bin/hw/android.hardware.graphics.allocator@4.0-service.minigbm_msm
-    interface android.hardware.graphics.allocator@4.0::IAllocator default
-    class hal animation
-    user system
-    group graphics drmrpc
-    capabilities SYS_NICE
-    onrestart restart surfaceflinger
-    writepid /dev/cpuset/system-background/tasks
diff --git a/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0.xml b/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0.xml
deleted file mode 100644
index 04695ef..0000000
--- a/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="device">
-    <hal format="hidl">
-        <name>android.hardware.graphics.allocator</name>
-        <transport>hwbinder</transport>
-        <version>4.0</version>
-        <interface>
-            <name>IAllocator</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-</manifest>
diff --git a/cros_gralloc/gralloc4/android.hardware.graphics.mapper@4.0.xml b/cros_gralloc/gralloc4/android.hardware.graphics.mapper@4.0.xml
deleted file mode 100644
index 3160c77..0000000
--- a/cros_gralloc/gralloc4/android.hardware.graphics.mapper@4.0.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="device">
-    <hal format="hidl">
-        <name>android.hardware.graphics.mapper</name>
-        <transport arch="32+64">passthrough</transport>
-        <version>4.0</version>
-        <interface>
-            <name>IMapper</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-</manifest>
diff --git a/dri.c b/dri.c
index 13d4833..97dc567 100644
--- a/dri.c
+++ b/dri.c
@@ -34,10 +34,7 @@
 	{ DRM_FORMAT_XBGR8888, __DRI_IMAGE_FORMAT_XBGR8888 },
 	{ DRM_FORMAT_ABGR8888, __DRI_IMAGE_FORMAT_ABGR8888 },
 	{ DRM_FORMAT_XRGB2101010, __DRI_IMAGE_FORMAT_XRGB2101010 },
-	{ DRM_FORMAT_XBGR2101010, __DRI_IMAGE_FORMAT_XBGR2101010 },
 	{ DRM_FORMAT_ARGB2101010, __DRI_IMAGE_FORMAT_ARGB2101010 },
-	{ DRM_FORMAT_ABGR2101010, __DRI_IMAGE_FORMAT_ABGR2101010 },
-	{ DRM_FORMAT_ABGR16161616F, __DRI_IMAGE_FORMAT_ABGR16161616F },
 };
 
 static int drm_format_to_dri_format(uint32_t drm_format)
@@ -72,9 +69,10 @@
  */
 static void close_gem_handle(uint32_t handle, int fd)
 {
-	struct drm_gem_close gem_close = { 0 };
+	struct drm_gem_close gem_close;
 	int ret = 0;
 
+	memset(&gem_close, 0, sizeof(gem_close));
 	gem_close.handle = handle;
 	ret = drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
 	if (ret)
@@ -95,21 +93,28 @@
 	if (dri->image_extension->queryImage(bo->priv, __DRI_IMAGE_ATTRIB_MODIFIER_UPPER,
 					     &modifier_upper) &&
 	    dri->image_extension->queryImage(bo->priv, __DRI_IMAGE_ATTRIB_MODIFIER_LOWER,
-					     &modifier_lower))
-		bo->meta.format_modifier =
+					     &modifier_lower)) {
+		bo->meta.format_modifiers[0] =
 		    ((uint64_t)modifier_upper << 32) | (uint32_t)modifier_lower;
-	else
-		bo->meta.format_modifier = DRM_FORMAT_MOD_INVALID;
+	} else {
+		bo->meta.format_modifiers[0] = DRM_FORMAT_MOD_INVALID;
+	}
 
-	if (!dri->image_extension->queryImage(bo->priv, __DRI_IMAGE_ATTRIB_NUM_PLANES, &num_planes))
+	if (!dri->image_extension->queryImage(bo->priv, __DRI_IMAGE_ATTRIB_NUM_PLANES,
+					      &num_planes)) {
 		return -errno;
+	}
 
 	bo->meta.num_planes = num_planes;
+
 	for (i = 0; i < num_planes; ++i) {
 		int prime_fd, stride, offset;
 		plane_image = dri->image_extension->fromPlanar(bo->priv, i, NULL);
 		__DRIimage *image = plane_image ? plane_image : bo->priv;
 
+		if (i)
+			bo->meta.format_modifiers[i] = bo->meta.format_modifiers[0];
+
 		if (!dri->image_extension->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &stride) ||
 		    !dri->image_extension->queryImage(image, __DRI_IMAGE_ATTRIB_OFFSET, &offset)) {
 			ret = -errno;
@@ -312,8 +317,9 @@
 	int ret, dri_format;
 	struct dri_driver *dri = bo->drv->priv;
 
-	if (!dri->image_extension->createImageWithModifiers)
+	if (!dri->image_extension->createImageWithModifiers) {
 		return -ENOENT;
+	}
 
 	dri_format = drm_format_to_dri_format(format);
 
@@ -340,7 +346,7 @@
 	int ret;
 	struct dri_driver *dri = bo->drv->priv;
 
-	if (data->format_modifier != DRM_FORMAT_MOD_INVALID) {
+	if (data->format_modifiers[0] != DRM_FORMAT_MOD_INVALID) {
 		unsigned error;
 
 		if (!dri->image_extension->createImageFromDmaBufs2)
@@ -348,8 +354,8 @@
 
 		// clang-format off
 		bo->priv = dri->image_extension->createImageFromDmaBufs2(dri->device, data->width, data->height,
-									 drv_get_standard_fourcc(data->format),
-									 data->format_modifier,
+									 data->format,
+									 data->format_modifiers[0],
 									 data->fds,
 									 bo->meta.num_planes,
 									 (int *)data->strides,
@@ -367,7 +373,7 @@
 	} else {
 		// clang-format off
 		bo->priv = dri->image_extension->createImageFromFds(dri->device, data->width, data->height,
-								    drv_get_standard_fourcc(data->format), data->fds,
+								    data->format, data->fds,
 								    bo->meta.num_planes,
 								    (int *)data->strides,
 								    (int *)data->offsets, NULL);
diff --git a/drv.c b/drv.c
index 9b43e9f..636cd07 100644
--- a/drv.c
+++ b/drv.c
@@ -28,36 +28,44 @@
 #ifdef DRV_AMDGPU
 extern const struct backend backend_amdgpu;
 #endif
+extern const struct backend backend_evdi;
 #ifdef DRV_EXYNOS
 extern const struct backend backend_exynos;
 #endif
 #ifdef DRV_I915
 extern const struct backend backend_i915;
 #endif
+#ifdef DRV_MARVELL
+extern const struct backend backend_marvell;
+#endif
 #ifdef DRV_MEDIATEK
 extern const struct backend backend_mediatek;
 #endif
+#ifdef DRV_MESON
+extern const struct backend backend_meson;
+#endif
 #ifdef DRV_MSM
 extern const struct backend backend_msm;
 #endif
+extern const struct backend backend_nouveau;
+#ifdef DRV_RADEON
+extern const struct backend backend_radeon;
+#endif
 #ifdef DRV_ROCKCHIP
 extern const struct backend backend_rockchip;
 #endif
+#ifdef DRV_SYNAPTICS
+extern const struct backend backend_synaptics;
+#endif
+#ifdef DRV_TEGRA
+extern const struct backend backend_tegra;
+#endif
+extern const struct backend backend_udl;
 #ifdef DRV_VC4
 extern const struct backend backend_vc4;
 #endif
-
-// Dumb / generic drivers
-extern const struct backend backend_evdi;
-extern const struct backend backend_marvell;
-extern const struct backend backend_meson;
-extern const struct backend backend_nouveau;
-extern const struct backend backend_komeda;
-extern const struct backend backend_radeon;
-extern const struct backend backend_synaptics;
-extern const struct backend backend_virtgpu;
-extern const struct backend backend_udl;
-extern const struct backend backend_vkms;
+extern const struct backend backend_vgem;
+extern const struct backend backend_virtio_gpu;
 
 static const struct backend *drv_get_backend(int fd)
 {
@@ -73,31 +81,55 @@
 #ifdef DRV_AMDGPU
 		&backend_amdgpu,
 #endif
+		&backend_evdi,
 #ifdef DRV_EXYNOS
 		&backend_exynos,
 #endif
 #ifdef DRV_I915
 		&backend_i915,
 #endif
+#ifdef DRV_MARVELL
+		&backend_marvell,
+#endif
 #ifdef DRV_MEDIATEK
 		&backend_mediatek,
 #endif
+#ifdef DRV_MESON
+		&backend_meson,
+#endif
 #ifdef DRV_MSM
 		&backend_msm,
 #endif
+		&backend_nouveau,
+#ifdef DRV_RADEON
+		&backend_radeon,
+#endif
 #ifdef DRV_ROCKCHIP
 		&backend_rockchip,
 #endif
+#ifdef DRV_SYNAPTICS
+		&backend_synaptics,
+#endif
+#ifdef DRV_TEGRA
+		&backend_tegra,
+#endif
+		&backend_udl,
 #ifdef DRV_VC4
 		&backend_vc4,
 #endif
-		&backend_evdi,	   &backend_marvell, &backend_meson,	 &backend_nouveau,
-		&backend_komeda,   &backend_radeon,  &backend_synaptics, &backend_virtgpu,
-		&backend_udl,	   &backend_virtgpu, &backend_vkms
+		&backend_vgem,	    &backend_virtio_gpu,
 	};
 
 	for (i = 0; i < ARRAY_SIZE(backend_list); i++) {
 		const struct backend *b = backend_list[i];
+		// Exactly one of the main create functions must be defined.
+		assert((b->bo_create != NULL) ^ (b->bo_create_from_metadata != NULL));
+		// Either both or neither must be implemented.
+		assert((b->bo_compute_metadata != NULL) == (b->bo_create_from_metadata != NULL));
+		// Both can't be defined, but it's okay for neither to be (i.e. only bo_create).
+		assert((b->bo_create_with_modifiers == NULL) ||
+		       (b->bo_create_from_metadata == NULL));
+
 		if (!strcmp(drm_version->name, b->name)) {
 			drmFreeVersion(drm_version);
 			return b;
@@ -118,10 +150,6 @@
 	if (!drv)
 		return NULL;
 
-	char *minigbm_debug;
-	minigbm_debug = getenv("MINIGBM_DEBUG");
-	drv->compression = (minigbm_debug == NULL) || (strcmp(minigbm_debug, "nocompression") != 0);
-
 	drv->fd = fd;
 	drv->backend = drv_get_backend(fd);
 
@@ -380,10 +408,10 @@
 		pthread_mutex_unlock(&bo->drv->driver_lock);
 	}
 
-	bo->meta.format_modifier = data->format_modifier;
 	for (plane = 0; plane < bo->meta.num_planes; plane++) {
 		bo->meta.strides[plane] = data->strides[plane];
 		bo->meta.offsets[plane] = data->offsets[plane];
+		bo->meta.format_modifiers[plane] = data->format_modifiers[plane];
 
 		seek_end = lseek(data->fds[plane], 0, SEEK_END);
 		if (seek_end == (off_t)(-1)) {
@@ -417,7 +445,7 @@
 {
 	uint32_t i;
 	uint8_t *addr;
-	struct mapping mapping = { 0 };
+	struct mapping mapping;
 
 	assert(rect->width >= 0);
 	assert(rect->height >= 0);
@@ -427,9 +455,11 @@
 	/* No CPU access for protected buffers. */
 	assert(!(bo->meta.use_flags & BO_USE_PROTECTED));
 
-	if (bo->is_test_buffer)
+	if (bo->is_test_buffer) {
 		return MAP_FAILED;
+	}
 
+	memset(&mapping, 0, sizeof(mapping));
 	mapping.rect = *rect;
 	mapping.refcount = 1;
 
@@ -591,8 +621,9 @@
 	int ret, fd;
 	assert(plane < bo->meta.num_planes);
 
-	if (bo->is_test_buffer)
+	if (bo->is_test_buffer) {
 		return -EINVAL;
+	}
 
 	ret = drmPrimeHandleToFD(bo->drv->fd, bo->handles[plane].u32, DRM_CLOEXEC | DRM_RDWR, &fd);
 
@@ -600,9 +631,6 @@
 	if (ret)
 		ret = drmPrimeHandleToFD(bo->drv->fd, bo->handles[plane].u32, DRM_CLOEXEC, &fd);
 
-	if (ret)
-		drv_log("Failed to get plane fd: %s\n", strerror(errno));
-
 	return (ret) ? ret : fd;
 }
 
@@ -624,9 +652,10 @@
 	return bo->meta.strides[plane];
 }
 
-uint64_t drv_bo_get_format_modifier(struct bo *bo)
+uint64_t drv_bo_get_plane_format_modifier(struct bo *bo, size_t plane)
 {
-	return bo->meta.format_modifier;
+	assert(plane < bo->meta.num_planes);
+	return bo->meta.format_modifiers[plane];
 }
 
 uint32_t drv_bo_get_format(struct bo *bo)
@@ -652,8 +681,9 @@
 	uint32_t count = 0;
 	size_t plane, p;
 
-	if (bo->is_test_buffer)
+	if (bo->is_test_buffer) {
 		return 0;
+	}
 
 	for (plane = 0; plane < bo->meta.num_planes; plane++) {
 		for (p = 0; p < plane; p++)
@@ -683,16 +713,15 @@
 }
 
 int drv_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES],
-		      uint32_t offsets[DRV_MAX_PLANES], uint64_t *format_modifier)
+		      uint32_t offsets[DRV_MAX_PLANES])
 {
 	for (uint32_t plane = 0; plane < bo->meta.num_planes; plane++) {
 		strides[plane] = bo->meta.strides[plane];
 		offsets[plane] = bo->meta.offsets[plane];
 	}
-	*format_modifier = bo->meta.format_modifier;
 
 	if (bo->drv->backend->resource_info)
-		return bo->drv->backend->resource_info(bo, strides, offsets, format_modifier);
+		return bo->drv->backend->resource_info(bo, strides, offsets);
 
 	return 0;
 }
diff --git a/drv.h b/drv.h
index 4689558..f19f9de 100644
--- a/drv.h
+++ b/drv.h
@@ -37,8 +37,7 @@
 #define BO_USE_HW_VIDEO_DECODER         (1ull << 13)
 #define BO_USE_HW_VIDEO_ENCODER         (1ull << 14)
 #define BO_USE_TEST_ALLOC		(1ull << 15)
-#define BO_USE_FRONT_RENDERING		(1ull << 16)
-#define BO_USE_RENDERSCRIPT		(1ull << 17)
+#define BO_USE_RENDERSCRIPT		(1ull << 16)
 
 /* Quirks for allocating a buffer. */
 #define BO_QUIRK_NONE			0
@@ -86,11 +85,10 @@
 	int fds[DRV_MAX_PLANES];
 	uint32_t strides[DRV_MAX_PLANES];
 	uint32_t offsets[DRV_MAX_PLANES];
-	uint64_t format_modifier;
+	uint64_t format_modifiers[DRV_MAX_PLANES];
 	uint32_t width;
 	uint32_t height;
 	uint32_t format;
-	uint32_t tiling;
 	uint64_t use_flags;
 };
 
@@ -167,7 +165,7 @@
 
 uint32_t drv_bo_get_plane_stride(struct bo *bo, size_t plane);
 
-uint64_t drv_bo_get_format_modifier(struct bo *bo);
+uint64_t drv_bo_get_plane_format_modifier(struct bo *bo, size_t plane);
 
 uint32_t drv_bo_get_format(struct bo *bo);
 
@@ -184,7 +182,7 @@
 uint32_t drv_num_buffers_per_bo(struct bo *bo);
 
 int drv_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES],
-		      uint32_t offsets[DRV_MAX_PLANES], uint64_t *format_modifier);
+		      uint32_t offsets[DRV_MAX_PLANES]);
 
 #define drv_log(format, ...)                                                                       \
 	do {                                                                                       \
diff --git a/drv_priv.h b/drv_priv.h
index c720077..32c082d 100644
--- a/drv_priv.h
+++ b/drv_priv.h
@@ -24,20 +24,9 @@
 	uint32_t offsets[DRV_MAX_PLANES];
 	uint32_t sizes[DRV_MAX_PLANES];
 	uint32_t strides[DRV_MAX_PLANES];
-	uint64_t format_modifier;
+	uint64_t format_modifiers[DRV_MAX_PLANES];
 	uint64_t use_flags;
 	size_t total_size;
-
-	/*
-	 * Most of the following metadata is virtgpu cross_domain specific.  However, that backend
-	 * needs to know traditional metadata (strides, offsets) in addition to this backend
-	 * specific metadata.  It's easiest just to stuff all the metadata here rather than
-	 * having two metadata structs.
-	 */
-	uint64_t blob_id;
-	uint32_t map_info;
-	int32_t memory_idx;
-	int32_t physical_device_idx;
 };
 
 struct bo {
@@ -68,7 +57,6 @@
 	struct drv_array *mappings;
 	struct drv_array *combos;
 	pthread_mutex_t driver_lock;
-	bool compression;
 };
 
 struct backend {
@@ -93,23 +81,23 @@
 	uint32_t (*resolve_format)(struct driver *drv, uint32_t format, uint64_t use_flags);
 	size_t (*num_planes_from_modifier)(struct driver *drv, uint32_t format, uint64_t modifier);
 	int (*resource_info)(struct bo *bo, uint32_t strides[DRV_MAX_PLANES],
-			     uint32_t offsets[DRV_MAX_PLANES], uint64_t *format_modifier);
+			     uint32_t offsets[DRV_MAX_PLANES]);
 };
 
 // clang-format off
-#define BO_USE_RENDER_MASK (BO_USE_LINEAR | BO_USE_RENDERING | BO_USE_RENDERSCRIPT | \
-			    BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN | BO_USE_SW_READ_RARELY | \
-			    BO_USE_SW_WRITE_RARELY | BO_USE_TEXTURE | BO_USE_FRONT_RENDERING)
+#define BO_USE_RENDER_MASK (BO_USE_LINEAR | BO_USE_PROTECTED | BO_USE_RENDERING | \
+	                   BO_USE_RENDERSCRIPT | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN | \
+                           BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY | BO_USE_TEXTURE)
 
-#define BO_USE_TEXTURE_MASK (BO_USE_LINEAR | BO_USE_RENDERSCRIPT | BO_USE_SW_READ_OFTEN | \
-			     BO_USE_SW_WRITE_OFTEN | BO_USE_SW_READ_RARELY | \
-			     BO_USE_SW_WRITE_RARELY | BO_USE_TEXTURE | BO_USE_FRONT_RENDERING)
+#define BO_USE_TEXTURE_MASK (BO_USE_LINEAR | BO_USE_PROTECTED | BO_USE_RENDERSCRIPT | \
+	                    BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN | \
+                            BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY | BO_USE_TEXTURE)
 
 #define BO_USE_SW_MASK (BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN | \
-			BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY | BO_USE_FRONT_RENDERING)
+		       BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY)
 
 #define BO_USE_NON_GPU_HW (BO_USE_SCANOUT | BO_USE_CAMERA_WRITE | BO_USE_CAMERA_READ | \
-			   BO_USE_HW_VIDEO_ENCODER | BO_USE_HW_VIDEO_DECODER)
+	                  BO_USE_HW_VIDEO_ENCODER | BO_USE_HW_VIDEO_DECODER)
 
 #ifndef DRM_FORMAT_MOD_LINEAR
 #define DRM_FORMAT_MOD_LINEAR DRM_FORMAT_MOD_NONE
diff --git a/dumb_driver.c b/dumb_driver.c
deleted file mode 100644
index f5a62aa..0000000
--- a/dumb_driver.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2020 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "drv_priv.h"
-#include "helpers.h"
-#include "util.h"
-
-#define INIT_DUMB_DRIVER(driver)                                                                   \
-	const struct backend backend_##driver = {                                                  \
-		.name = #driver,                                                                   \
-		.init = dumb_driver_init,                                                          \
-		.bo_create = drv_dumb_bo_create,                                                   \
-		.bo_destroy = drv_dumb_bo_destroy,                                                 \
-		.bo_import = drv_prime_bo_import,                                                  \
-		.bo_map = drv_dumb_bo_map,                                                         \
-		.bo_unmap = drv_bo_munmap,                                                         \
-	};
-
-static const uint32_t scanout_render_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888,
-						   DRM_FORMAT_ABGR8888, DRM_FORMAT_XBGR8888,
-						   DRM_FORMAT_BGR888,	DRM_FORMAT_BGR565 };
-
-static const uint32_t texture_only_formats[] = { DRM_FORMAT_NV12, DRM_FORMAT_NV21,
-						 DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID };
-
-static int dumb_driver_init(struct driver *drv)
-{
-	drv_add_combinations(drv, scanout_render_formats, ARRAY_SIZE(scanout_render_formats),
-			     &LINEAR_METADATA, BO_USE_RENDER_MASK | BO_USE_SCANOUT);
-
-	drv_add_combinations(drv, texture_only_formats, ARRAY_SIZE(texture_only_formats),
-			     &LINEAR_METADATA, BO_USE_TEXTURE_MASK);
-
-	drv_modify_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA,
-			       BO_USE_HW_VIDEO_ENCODER | BO_USE_HW_VIDEO_DECODER |
-				   BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
-	drv_modify_combination(drv, DRM_FORMAT_NV21, &LINEAR_METADATA, BO_USE_HW_VIDEO_ENCODER);
-
-	return drv_modify_linear_combinations(drv);
-}
-
-INIT_DUMB_DRIVER(evdi)
-INIT_DUMB_DRIVER(komeda)
-INIT_DUMB_DRIVER(marvell)
-INIT_DUMB_DRIVER(meson)
-INIT_DUMB_DRIVER(nouveau)
-INIT_DUMB_DRIVER(radeon)
-INIT_DUMB_DRIVER(synaptics)
-INIT_DUMB_DRIVER(udl)
-INIT_DUMB_DRIVER(vkms)
diff --git a/evdi.c b/evdi.c
new file mode 100644
index 0000000..bfa62a0
--- /dev/null
+++ b/evdi.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2016 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 };
+
+static int evdi_init(struct driver *drv)
+{
+	drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+			     &LINEAR_METADATA, BO_USE_RENDER_MASK);
+
+	return drv_modify_linear_combinations(drv);
+}
+
+const struct backend backend_evdi = {
+	.name = "evdi",
+	.init = evdi_init,
+	.bo_create = drv_dumb_bo_create,
+	.bo_destroy = drv_dumb_bo_destroy,
+	.bo_import = drv_prime_bo_import,
+	.bo_map = drv_dumb_bo_map,
+	.bo_unmap = drv_bo_munmap,
+};
diff --git a/external/i915_drm.h b/external/i915_drm.h
deleted file mode 100644
index f5991a8..0000000
--- a/external/i915_drm.h
+++ /dev/null
@@ -1,2422 +0,0 @@
-/*
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#ifndef _UAPI_I915_DRM_H_
-#define _UAPI_I915_DRM_H_
-
-#include "drm.h"
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-/* Please note that modifications to all structs defined here are
- * subject to backwards-compatibility constraints.
- */
-
-/**
- * DOC: uevents generated by i915 on it's device node
- *
- * I915_L3_PARITY_UEVENT - Generated when the driver receives a parity mismatch
- *	event from the gpu l3 cache. Additional information supplied is ROW,
- *	BANK, SUBBANK, SLICE of the affected cacheline. Userspace should keep
- *	track of these events and if a specific cache-line seems to have a
- *	persistent error remap it with the l3 remapping tool supplied in
- *	intel-gpu-tools.  The value supplied with the event is always 1.
- *
- * I915_ERROR_UEVENT - Generated upon error detection, currently only via
- *	hangcheck. The error detection event is a good indicator of when things
- *	began to go badly. The value supplied with the event is a 1 upon error
- *	detection, and a 0 upon reset completion, signifying no more error
- *	exists. NOTE: Disabling hangcheck or reset via module parameter will
- *	cause the related events to not be seen.
- *
- * I915_RESET_UEVENT - Event is generated just before an attempt to reset the
- *	the GPU. The value supplied with the event is always 1. NOTE: Disable
- *	reset via module parameter will cause this event to not be seen.
- */
-#define I915_L3_PARITY_UEVENT		"L3_PARITY_ERROR"
-#define I915_ERROR_UEVENT		"ERROR"
-#define I915_RESET_UEVENT		"RESET"
-
-/*
- * i915_user_extension: Base class for defining a chain of extensions
- *
- * Many interfaces need to grow over time. In most cases we can simply
- * extend the struct and have userspace pass in more data. Another option,
- * as demonstrated by Vulkan's approach to providing extensions for forward
- * and backward compatibility, is to use a list of optional structs to
- * provide those extra details.
- *
- * The key advantage to using an extension chain is that it allows us to
- * redefine the interface more easily than an ever growing struct of
- * increasing complexity, and for large parts of that interface to be
- * entirely optional. The downside is more pointer chasing; chasing across
- * the __user boundary with pointers encapsulated inside u64.
- */
-struct i915_user_extension {
-	__u64 next_extension;
-	__u32 name;
-	__u32 flags; /* All undefined bits must be zero. */
-	__u32 rsvd[4]; /* Reserved for future use; must be zero. */
-};
-
-/*
- * MOCS indexes used for GPU surfaces, defining the cacheability of the
- * surface data and the coherency for this data wrt. CPU vs. GPU accesses.
- */
-enum i915_mocs_table_index {
-	/*
-	 * Not cached anywhere, coherency between CPU and GPU accesses is
-	 * guaranteed.
-	 */
-	I915_MOCS_UNCACHED,
-	/*
-	 * Cacheability and coherency controlled by the kernel automatically
-	 * based on the DRM_I915_GEM_SET_CACHING IOCTL setting and the current
-	 * usage of the surface (used for display scanout or not).
-	 */
-	I915_MOCS_PTE,
-	/*
-	 * Cached in all GPU caches available on the platform.
-	 * Coherency between CPU and GPU accesses to the surface is not
-	 * guaranteed without extra synchronization.
-	 */
-	I915_MOCS_CACHED,
-};
-
-/*
- * Different engines serve different roles, and there may be more than one
- * engine serving each role. enum drm_i915_gem_engine_class provides a
- * classification of the role of the engine, which may be used when requesting
- * operations to be performed on a certain subset of engines, or for providing
- * information about that group.
- */
-enum drm_i915_gem_engine_class {
-	I915_ENGINE_CLASS_RENDER	= 0,
-	I915_ENGINE_CLASS_COPY		= 1,
-	I915_ENGINE_CLASS_VIDEO		= 2,
-	I915_ENGINE_CLASS_VIDEO_ENHANCE	= 3,
-
-	/* should be kept compact */
-
-	I915_ENGINE_CLASS_INVALID	= -1
-};
-
-/*
- * There may be more than one engine fulfilling any role within the system.
- * Each engine of a class is given a unique instance number and therefore
- * any engine can be specified by its class:instance tuplet. APIs that allow
- * access to any engine in the system will use struct i915_engine_class_instance
- * for this identification.
- */
-struct i915_engine_class_instance {
-	__u16 engine_class; /* see enum drm_i915_gem_engine_class */
-	__u16 engine_instance;
-#define I915_ENGINE_CLASS_INVALID_NONE -1
-#define I915_ENGINE_CLASS_INVALID_VIRTUAL -2
-};
-
-/**
- * DOC: perf_events exposed by i915 through /sys/bus/event_sources/drivers/i915
- *
- */
-
-enum drm_i915_pmu_engine_sample {
-	I915_SAMPLE_BUSY = 0,
-	I915_SAMPLE_WAIT = 1,
-	I915_SAMPLE_SEMA = 2
-};
-
-#define I915_PMU_SAMPLE_BITS (4)
-#define I915_PMU_SAMPLE_MASK (0xf)
-#define I915_PMU_SAMPLE_INSTANCE_BITS (8)
-#define I915_PMU_CLASS_SHIFT \
-	(I915_PMU_SAMPLE_BITS + I915_PMU_SAMPLE_INSTANCE_BITS)
-
-#define __I915_PMU_ENGINE(class, instance, sample) \
-	((class) << I915_PMU_CLASS_SHIFT | \
-	(instance) << I915_PMU_SAMPLE_BITS | \
-	(sample))
-
-#define I915_PMU_ENGINE_BUSY(class, instance) \
-	__I915_PMU_ENGINE(class, instance, I915_SAMPLE_BUSY)
-
-#define I915_PMU_ENGINE_WAIT(class, instance) \
-	__I915_PMU_ENGINE(class, instance, I915_SAMPLE_WAIT)
-
-#define I915_PMU_ENGINE_SEMA(class, instance) \
-	__I915_PMU_ENGINE(class, instance, I915_SAMPLE_SEMA)
-
-#define __I915_PMU_OTHER(x) (__I915_PMU_ENGINE(0xff, 0xff, 0xf) + 1 + (x))
-
-#define I915_PMU_ACTUAL_FREQUENCY	__I915_PMU_OTHER(0)
-#define I915_PMU_REQUESTED_FREQUENCY	__I915_PMU_OTHER(1)
-#define I915_PMU_INTERRUPTS		__I915_PMU_OTHER(2)
-#define I915_PMU_RC6_RESIDENCY		__I915_PMU_OTHER(3)
-
-#define I915_PMU_LAST I915_PMU_RC6_RESIDENCY
-
-/* Each region is a minimum of 16k, and there are at most 255 of them.
- */
-#define I915_NR_TEX_REGIONS 255	/* table size 2k - maximum due to use
-				 * of chars for next/prev indices */
-#define I915_LOG_MIN_TEX_REGION_SIZE 14
-
-typedef struct _drm_i915_init {
-	enum {
-		I915_INIT_DMA = 0x01,
-		I915_CLEANUP_DMA = 0x02,
-		I915_RESUME_DMA = 0x03
-	} func;
-	unsigned int mmio_offset;
-	int sarea_priv_offset;
-	unsigned int ring_start;
-	unsigned int ring_end;
-	unsigned int ring_size;
-	unsigned int front_offset;
-	unsigned int back_offset;
-	unsigned int depth_offset;
-	unsigned int w;
-	unsigned int h;
-	unsigned int pitch;
-	unsigned int pitch_bits;
-	unsigned int back_pitch;
-	unsigned int depth_pitch;
-	unsigned int cpp;
-	unsigned int chipset;
-} drm_i915_init_t;
-
-typedef struct _drm_i915_sarea {
-	struct drm_tex_region texList[I915_NR_TEX_REGIONS + 1];
-	int last_upload;	/* last time texture was uploaded */
-	int last_enqueue;	/* last time a buffer was enqueued */
-	int last_dispatch;	/* age of the most recently dispatched buffer */
-	int ctxOwner;		/* last context to upload state */
-	int texAge;
-	int pf_enabled;		/* is pageflipping allowed? */
-	int pf_active;
-	int pf_current_page;	/* which buffer is being displayed? */
-	int perf_boxes;		/* performance boxes to be displayed */
-	int width, height;      /* screen size in pixels */
-
-	drm_handle_t front_handle;
-	int front_offset;
-	int front_size;
-
-	drm_handle_t back_handle;
-	int back_offset;
-	int back_size;
-
-	drm_handle_t depth_handle;
-	int depth_offset;
-	int depth_size;
-
-	drm_handle_t tex_handle;
-	int tex_offset;
-	int tex_size;
-	int log_tex_granularity;
-	int pitch;
-	int rotation;           /* 0, 90, 180 or 270 */
-	int rotated_offset;
-	int rotated_size;
-	int rotated_pitch;
-	int virtualX, virtualY;
-
-	unsigned int front_tiled;
-	unsigned int back_tiled;
-	unsigned int depth_tiled;
-	unsigned int rotated_tiled;
-	unsigned int rotated2_tiled;
-
-	int pipeA_x;
-	int pipeA_y;
-	int pipeA_w;
-	int pipeA_h;
-	int pipeB_x;
-	int pipeB_y;
-	int pipeB_w;
-	int pipeB_h;
-
-	/* fill out some space for old userspace triple buffer */
-	drm_handle_t unused_handle;
-	__u32 unused1, unused2, unused3;
-
-	/* buffer object handles for static buffers. May change
-	 * over the lifetime of the client.
-	 */
-	__u32 front_bo_handle;
-	__u32 back_bo_handle;
-	__u32 unused_bo_handle;
-	__u32 depth_bo_handle;
-
-} drm_i915_sarea_t;
-
-/* due to userspace building against these headers we need some compat here */
-#define planeA_x pipeA_x
-#define planeA_y pipeA_y
-#define planeA_w pipeA_w
-#define planeA_h pipeA_h
-#define planeB_x pipeB_x
-#define planeB_y pipeB_y
-#define planeB_w pipeB_w
-#define planeB_h pipeB_h
-
-/* Flags for perf_boxes
- */
-#define I915_BOX_RING_EMPTY    0x1
-#define I915_BOX_FLIP          0x2
-#define I915_BOX_WAIT          0x4
-#define I915_BOX_TEXTURE_LOAD  0x8
-#define I915_BOX_LOST_CONTEXT  0x10
-
-/*
- * i915 specific ioctls.
- *
- * The device specific ioctl range is [DRM_COMMAND_BASE, DRM_COMMAND_END) ie
- * [0x40, 0xa0) (a0 is excluded). The numbers below are defined as offset
- * against DRM_COMMAND_BASE and should be between [0x0, 0x60).
- */
-#define DRM_I915_INIT		0x00
-#define DRM_I915_FLUSH		0x01
-#define DRM_I915_FLIP		0x02
-#define DRM_I915_BATCHBUFFER	0x03
-#define DRM_I915_IRQ_EMIT	0x04
-#define DRM_I915_IRQ_WAIT	0x05
-#define DRM_I915_GETPARAM	0x06
-#define DRM_I915_SETPARAM	0x07
-#define DRM_I915_ALLOC		0x08
-#define DRM_I915_FREE		0x09
-#define DRM_I915_INIT_HEAP	0x0a
-#define DRM_I915_CMDBUFFER	0x0b
-#define DRM_I915_DESTROY_HEAP	0x0c
-#define DRM_I915_SET_VBLANK_PIPE	0x0d
-#define DRM_I915_GET_VBLANK_PIPE	0x0e
-#define DRM_I915_VBLANK_SWAP	0x0f
-#define DRM_I915_HWS_ADDR	0x11
-#define DRM_I915_GEM_INIT	0x13
-#define DRM_I915_GEM_EXECBUFFER	0x14
-#define DRM_I915_GEM_PIN	0x15
-#define DRM_I915_GEM_UNPIN	0x16
-#define DRM_I915_GEM_BUSY	0x17
-#define DRM_I915_GEM_THROTTLE	0x18
-#define DRM_I915_GEM_ENTERVT	0x19
-#define DRM_I915_GEM_LEAVEVT	0x1a
-#define DRM_I915_GEM_CREATE	0x1b
-#define DRM_I915_GEM_PREAD	0x1c
-#define DRM_I915_GEM_PWRITE	0x1d
-#define DRM_I915_GEM_MMAP	0x1e
-#define DRM_I915_GEM_SET_DOMAIN	0x1f
-#define DRM_I915_GEM_SW_FINISH	0x20
-#define DRM_I915_GEM_SET_TILING	0x21
-#define DRM_I915_GEM_GET_TILING	0x22
-#define DRM_I915_GEM_GET_APERTURE 0x23
-#define DRM_I915_GEM_MMAP_GTT	0x24
-#define DRM_I915_GET_PIPE_FROM_CRTC_ID	0x25
-#define DRM_I915_GEM_MADVISE	0x26
-#define DRM_I915_OVERLAY_PUT_IMAGE	0x27
-#define DRM_I915_OVERLAY_ATTRS	0x28
-#define DRM_I915_GEM_EXECBUFFER2	0x29
-#define DRM_I915_GEM_EXECBUFFER2_WR	DRM_I915_GEM_EXECBUFFER2
-#define DRM_I915_GET_SPRITE_COLORKEY	0x2a
-#define DRM_I915_SET_SPRITE_COLORKEY	0x2b
-#define DRM_I915_GEM_WAIT	0x2c
-#define DRM_I915_GEM_CONTEXT_CREATE	0x2d
-#define DRM_I915_GEM_CONTEXT_DESTROY	0x2e
-#define DRM_I915_GEM_SET_CACHING	0x2f
-#define DRM_I915_GEM_GET_CACHING	0x30
-#define DRM_I915_REG_READ		0x31
-#define DRM_I915_GET_RESET_STATS	0x32
-#define DRM_I915_GEM_USERPTR		0x33
-#define DRM_I915_GEM_CONTEXT_GETPARAM	0x34
-#define DRM_I915_GEM_CONTEXT_SETPARAM	0x35
-#define DRM_I915_PERF_OPEN		0x36
-#define DRM_I915_PERF_ADD_CONFIG	0x37
-#define DRM_I915_PERF_REMOVE_CONFIG	0x38
-#define DRM_I915_QUERY			0x39
-#define DRM_I915_GEM_VM_CREATE		0x3a
-#define DRM_I915_GEM_VM_DESTROY		0x3b
-#define DRM_I915_PXP_OPS		0x3c
-/* Must be kept compact -- no holes */
-
-#define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
-#define DRM_IOCTL_I915_FLUSH		DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
-#define DRM_IOCTL_I915_FLIP		DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLIP)
-#define DRM_IOCTL_I915_BATCHBUFFER	DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t)
-#define DRM_IOCTL_I915_IRQ_EMIT         DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t)
-#define DRM_IOCTL_I915_IRQ_WAIT         DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t)
-#define DRM_IOCTL_I915_GETPARAM         DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GETPARAM, drm_i915_getparam_t)
-#define DRM_IOCTL_I915_SETPARAM         DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SETPARAM, drm_i915_setparam_t)
-#define DRM_IOCTL_I915_ALLOC            DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_ALLOC, drm_i915_mem_alloc_t)
-#define DRM_IOCTL_I915_FREE             DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FREE, drm_i915_mem_free_t)
-#define DRM_IOCTL_I915_INIT_HEAP        DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t)
-#define DRM_IOCTL_I915_CMDBUFFER	DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t)
-#define DRM_IOCTL_I915_DESTROY_HEAP	DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t)
-#define DRM_IOCTL_I915_SET_VBLANK_PIPE	DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
-#define DRM_IOCTL_I915_GET_VBLANK_PIPE	DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
-#define DRM_IOCTL_I915_VBLANK_SWAP	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
-#define DRM_IOCTL_I915_HWS_ADDR		DRM_IOW(DRM_COMMAND_BASE + DRM_I915_HWS_ADDR, struct drm_i915_gem_init)
-#define DRM_IOCTL_I915_GEM_INIT		DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_INIT, struct drm_i915_gem_init)
-#define DRM_IOCTL_I915_GEM_EXECBUFFER	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER, struct drm_i915_gem_execbuffer)
-#define DRM_IOCTL_I915_GEM_EXECBUFFER2	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2, struct drm_i915_gem_execbuffer2)
-#define DRM_IOCTL_I915_GEM_EXECBUFFER2_WR	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2_WR, struct drm_i915_gem_execbuffer2)
-#define DRM_IOCTL_I915_GEM_PIN		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin)
-#define DRM_IOCTL_I915_GEM_UNPIN	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin)
-#define DRM_IOCTL_I915_GEM_BUSY		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy)
-#define DRM_IOCTL_I915_GEM_SET_CACHING		DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_SET_CACHING, struct drm_i915_gem_caching)
-#define DRM_IOCTL_I915_GEM_GET_CACHING		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_GET_CACHING, struct drm_i915_gem_caching)
-#define DRM_IOCTL_I915_GEM_THROTTLE	DRM_IO ( DRM_COMMAND_BASE + DRM_I915_GEM_THROTTLE)
-#define DRM_IOCTL_I915_GEM_ENTERVT	DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_ENTERVT)
-#define DRM_IOCTL_I915_GEM_LEAVEVT	DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_LEAVEVT)
-#define DRM_IOCTL_I915_GEM_CREATE	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CREATE, struct drm_i915_gem_create)
-#define DRM_IOCTL_I915_GEM_CREATE_EXT   DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CREATE, struct drm_i915_gem_create_ext)
-#define DRM_IOCTL_I915_GEM_PREAD	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PREAD, struct drm_i915_gem_pread)
-#define DRM_IOCTL_I915_GEM_PWRITE	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite)
-#define DRM_IOCTL_I915_GEM_MMAP		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap)
-#define DRM_IOCTL_I915_GEM_MMAP_GTT	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP_GTT, struct drm_i915_gem_mmap_gtt)
-#define DRM_IOCTL_I915_GEM_MMAP_OFFSET	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP_GTT, struct drm_i915_gem_mmap_offset)
-#define DRM_IOCTL_I915_GEM_SET_DOMAIN	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain)
-#define DRM_IOCTL_I915_GEM_SW_FINISH	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish)
-#define DRM_IOCTL_I915_GEM_SET_TILING	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling)
-#define DRM_IOCTL_I915_GEM_GET_TILING	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct drm_i915_gem_get_tiling)
-#define DRM_IOCTL_I915_GEM_GET_APERTURE	DRM_IOR  (DRM_COMMAND_BASE + DRM_I915_GEM_GET_APERTURE, struct drm_i915_gem_get_aperture)
-#define DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_PIPE_FROM_CRTC_ID, struct drm_i915_get_pipe_from_crtc_id)
-#define DRM_IOCTL_I915_GEM_MADVISE	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise)
-#define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_OVERLAY_PUT_IMAGE, struct drm_intel_overlay_put_image)
-#define DRM_IOCTL_I915_OVERLAY_ATTRS	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs)
-#define DRM_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
-#define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
-#define DRM_IOCTL_I915_GEM_WAIT		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_WAIT, struct drm_i915_gem_wait)
-#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create)
-#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create_ext)
-#define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy)
-#define DRM_IOCTL_I915_REG_READ			DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_REG_READ, struct drm_i915_reg_read)
-#define DRM_IOCTL_I915_GET_RESET_STATS		DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GET_RESET_STATS, struct drm_i915_reset_stats)
-#define DRM_IOCTL_I915_GEM_USERPTR			DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_USERPTR, struct drm_i915_gem_userptr)
-#define DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_GETPARAM, struct drm_i915_gem_context_param)
-#define DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_SETPARAM, struct drm_i915_gem_context_param)
-#define DRM_IOCTL_I915_PERF_OPEN	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param)
-#define DRM_IOCTL_I915_PERF_ADD_CONFIG	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config)
-#define DRM_IOCTL_I915_PERF_REMOVE_CONFIG	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64)
-#define DRM_IOCTL_I915_QUERY			DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query)
-#define DRM_IOCTL_I915_GEM_VM_CREATE	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_VM_CREATE, struct drm_i915_gem_vm_control)
-#define DRM_IOCTL_I915_GEM_VM_DESTROY	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_VM_DESTROY, struct drm_i915_gem_vm_control)
-#define DRM_IOCTL_I915_PXP_OPS		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_PXP_OPS, struct drm_i915_pxp_ops)
-
-/* Allow drivers to submit batchbuffers directly to hardware, relying
- * on the security mechanisms provided by hardware.
- */
-typedef struct drm_i915_batchbuffer {
-	int start;		/* agp offset */
-	int used;		/* nr bytes in use */
-	int DR1;		/* hw flags for GFX_OP_DRAWRECT_INFO */
-	int DR4;		/* window origin for GFX_OP_DRAWRECT_INFO */
-	int num_cliprects;	/* mulitpass with multiple cliprects? */
-	struct drm_clip_rect *cliprects;	/* pointer to userspace cliprects */
-} drm_i915_batchbuffer_t;
-
-/* As above, but pass a pointer to userspace buffer which can be
- * validated by the kernel prior to sending to hardware.
- */
-typedef struct _drm_i915_cmdbuffer {
-	char *buf;	/* pointer to userspace command buffer */
-	int sz;			/* nr bytes in buf */
-	int DR1;		/* hw flags for GFX_OP_DRAWRECT_INFO */
-	int DR4;		/* window origin for GFX_OP_DRAWRECT_INFO */
-	int num_cliprects;	/* mulitpass with multiple cliprects? */
-	struct drm_clip_rect *cliprects;	/* pointer to userspace cliprects */
-} drm_i915_cmdbuffer_t;
-
-/* Userspace can request & wait on irq's:
- */
-typedef struct drm_i915_irq_emit {
-	int *irq_seq;
-} drm_i915_irq_emit_t;
-
-typedef struct drm_i915_irq_wait {
-	int irq_seq;
-} drm_i915_irq_wait_t;
-
-/*
- * Different modes of per-process Graphics Translation Table,
- * see I915_PARAM_HAS_ALIASING_PPGTT
- */
-#define I915_GEM_PPGTT_NONE	0
-#define I915_GEM_PPGTT_ALIASING	1
-#define I915_GEM_PPGTT_FULL	2
-
-/* Ioctl to query kernel params:
- */
-#define I915_PARAM_IRQ_ACTIVE            1
-#define I915_PARAM_ALLOW_BATCHBUFFER     2
-#define I915_PARAM_LAST_DISPATCH         3
-#define I915_PARAM_CHIPSET_ID            4
-#define I915_PARAM_HAS_GEM               5
-#define I915_PARAM_NUM_FENCES_AVAIL      6
-#define I915_PARAM_HAS_OVERLAY           7
-#define I915_PARAM_HAS_PAGEFLIPPING	 8
-#define I915_PARAM_HAS_EXECBUF2          9
-#define I915_PARAM_HAS_BSD		 10
-#define I915_PARAM_HAS_BLT		 11
-#define I915_PARAM_HAS_RELAXED_FENCING	 12
-#define I915_PARAM_HAS_COHERENT_RINGS	 13
-#define I915_PARAM_HAS_EXEC_CONSTANTS	 14
-#define I915_PARAM_HAS_RELAXED_DELTA	 15
-#define I915_PARAM_HAS_GEN7_SOL_RESET	 16
-#define I915_PARAM_HAS_LLC     	 	 17
-#define I915_PARAM_HAS_ALIASING_PPGTT	 18
-#define I915_PARAM_HAS_WAIT_TIMEOUT	 19
-#define I915_PARAM_HAS_SEMAPHORES	 20
-#define I915_PARAM_HAS_PRIME_VMAP_FLUSH	 21
-#define I915_PARAM_HAS_VEBOX		 22
-#define I915_PARAM_HAS_SECURE_BATCHES	 23
-#define I915_PARAM_HAS_PINNED_BATCHES	 24
-#define I915_PARAM_HAS_EXEC_NO_RELOC	 25
-#define I915_PARAM_HAS_EXEC_HANDLE_LUT   26
-#define I915_PARAM_HAS_WT     	 	 27
-#define I915_PARAM_CMD_PARSER_VERSION	 28
-#define I915_PARAM_HAS_COHERENT_PHYS_GTT 29
-#define I915_PARAM_MMAP_VERSION          30
-#define I915_PARAM_HAS_BSD2		 31
-#define I915_PARAM_REVISION              32
-#define I915_PARAM_SUBSLICE_TOTAL	 33
-#define I915_PARAM_EU_TOTAL		 34
-#define I915_PARAM_HAS_GPU_RESET	 35
-#define I915_PARAM_HAS_RESOURCE_STREAMER 36
-#define I915_PARAM_HAS_EXEC_SOFTPIN	 37
-#define I915_PARAM_HAS_POOLED_EU	 38
-#define I915_PARAM_MIN_EU_IN_POOL	 39
-#define I915_PARAM_MMAP_GTT_VERSION	 40
-
-/*
- * Query whether DRM_I915_GEM_EXECBUFFER2 supports user defined execution
- * priorities and the driver will attempt to execute batches in priority order.
- * The param returns a capability bitmask, nonzero implies that the scheduler
- * is enabled, with different features present according to the mask.
- *
- * The initial priority for each batch is supplied by the context and is
- * controlled via I915_CONTEXT_PARAM_PRIORITY.
- */
-#define I915_PARAM_HAS_SCHEDULER	 41
-#define   I915_SCHEDULER_CAP_ENABLED	(1ul << 0)
-#define   I915_SCHEDULER_CAP_PRIORITY	(1ul << 1)
-#define   I915_SCHEDULER_CAP_PREEMPTION	(1ul << 2)
-#define   I915_SCHEDULER_CAP_SEMAPHORES	(1ul << 3)
-#define   I915_SCHEDULER_CAP_ENGINE_BUSY_STATS	(1ul << 4)
-
-#define I915_PARAM_HUC_STATUS		 42
-
-/* Query whether DRM_I915_GEM_EXECBUFFER2 supports the ability to opt-out of
- * synchronisation with implicit fencing on individual objects.
- * See EXEC_OBJECT_ASYNC.
- */
-#define I915_PARAM_HAS_EXEC_ASYNC	 43
-
-/* Query whether DRM_I915_GEM_EXECBUFFER2 supports explicit fence support -
- * both being able to pass in a sync_file fd to wait upon before executing,
- * and being able to return a new sync_file fd that is signaled when the
- * current request is complete. See I915_EXEC_FENCE_IN and I915_EXEC_FENCE_OUT.
- */
-#define I915_PARAM_HAS_EXEC_FENCE	 44
-
-/* Query whether DRM_I915_GEM_EXECBUFFER2 supports the ability to capture
- * user specified bufffers for post-mortem debugging of GPU hangs. See
- * EXEC_OBJECT_CAPTURE.
- */
-#define I915_PARAM_HAS_EXEC_CAPTURE	 45
-
-#define I915_PARAM_SLICE_MASK		 46
-
-/* Assuming it's uniform for each slice, this queries the mask of subslices
- * per-slice for this system.
- */
-#define I915_PARAM_SUBSLICE_MASK	 47
-
-/*
- * Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying the batch buffer
- * as the first execobject as opposed to the last. See I915_EXEC_BATCH_FIRST.
- */
-#define I915_PARAM_HAS_EXEC_BATCH_FIRST	 48
-
-/* Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying an array of
- * drm_i915_gem_exec_fence structures.  See I915_EXEC_FENCE_ARRAY.
- */
-#define I915_PARAM_HAS_EXEC_FENCE_ARRAY  49
-
-/*
- * Query whether every context (both per-file default and user created) is
- * isolated (insofar as HW supports). If this parameter is not true, then
- * freshly created contexts may inherit values from an existing context,
- * rather than default HW values. If true, it also ensures (insofar as HW
- * supports) that all state set by this context will not leak to any other
- * context.
- *
- * As not every engine across every gen support contexts, the returned
- * value reports the support of context isolation for individual engines by
- * returning a bitmask of each engine class set to true if that class supports
- * isolation.
- */
-#define I915_PARAM_HAS_CONTEXT_ISOLATION 50
-
-/* Frequency of the command streamer timestamps given by the *_TIMESTAMP
- * registers. This used to be fixed per platform but from CNL onwards, this
- * might vary depending on the parts.
- */
-#define I915_PARAM_CS_TIMESTAMP_FREQUENCY 51
-
-/*
- * Once upon a time we supposed that writes through the GGTT would be
- * immediately in physical memory (once flushed out of the CPU path). However,
- * on a few different processors and chipsets, this is not necessarily the case
- * as the writes appear to be buffered internally. Thus a read of the backing
- * storage (physical memory) via a different path (with different physical tags
- * to the indirect write via the GGTT) will see stale values from before
- * the GGTT write. Inside the kernel, we can for the most part keep track of
- * the different read/write domains in use (e.g. set-domain), but the assumption
- * of coherency is baked into the ABI, hence reporting its true state in this
- * parameter.
- *
- * Reports true when writes via mmap_gtt are immediately visible following an
- * lfence to flush the WCB.
- *
- * Reports false when writes via mmap_gtt are indeterminately delayed in an in
- * internal buffer and are _not_ immediately visible to third parties accessing
- * directly via mmap_cpu/mmap_wc. Use of mmap_gtt as part of an IPC
- * communications channel when reporting false is strongly disadvised.
- */
-#define I915_PARAM_MMAP_GTT_COHERENT	52
-
-/*
- * Query whether DRM_I915_GEM_EXECBUFFER2 supports coordination of parallel
- * execution through use of explicit fence support.
- * See I915_EXEC_FENCE_OUT and I915_EXEC_FENCE_SUBMIT.
- */
-#define I915_PARAM_HAS_EXEC_SUBMIT_FENCE 53
-
-/*
- * Revision of the i915-perf uAPI. The value returned helps determine what
- * i915-perf features are available. See drm_i915_perf_property_id.
- */
-#define I915_PARAM_PERF_REVISION	54
-
-/* Must be kept compact -- no holes and well documented */
-
-typedef struct drm_i915_getparam {
-	__s32 param;
-	/*
-	 * WARNING: Using pointers instead of fixed-size u64 means we need to write
-	 * compat32 code. Don't repeat this mistake.
-	 */
-	int *value;
-} drm_i915_getparam_t;
-
-/* Ioctl to set kernel params:
- */
-#define I915_SETPARAM_USE_MI_BATCHBUFFER_START            1
-#define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY             2
-#define I915_SETPARAM_ALLOW_BATCHBUFFER                   3
-#define I915_SETPARAM_NUM_USED_FENCES                     4
-/* Must be kept compact -- no holes */
-
-typedef struct drm_i915_setparam {
-	int param;
-	int value;
-} drm_i915_setparam_t;
-
-/* A memory manager for regions of shared memory:
- */
-#define I915_MEM_REGION_AGP 1
-
-typedef struct drm_i915_mem_alloc {
-	int region;
-	int alignment;
-	int size;
-	int *region_offset;	/* offset from start of fb or agp */
-} drm_i915_mem_alloc_t;
-
-typedef struct drm_i915_mem_free {
-	int region;
-	int region_offset;
-} drm_i915_mem_free_t;
-
-typedef struct drm_i915_mem_init_heap {
-	int region;
-	int size;
-	int start;
-} drm_i915_mem_init_heap_t;
-
-/* Allow memory manager to be torn down and re-initialized (eg on
- * rotate):
- */
-typedef struct drm_i915_mem_destroy_heap {
-	int region;
-} drm_i915_mem_destroy_heap_t;
-
-/* Allow X server to configure which pipes to monitor for vblank signals
- */
-#define	DRM_I915_VBLANK_PIPE_A	1
-#define	DRM_I915_VBLANK_PIPE_B	2
-
-typedef struct drm_i915_vblank_pipe {
-	int pipe;
-} drm_i915_vblank_pipe_t;
-
-/* Schedule buffer swap at given vertical blank:
- */
-typedef struct drm_i915_vblank_swap {
-	drm_drawable_t drawable;
-	enum drm_vblank_seq_type seqtype;
-	unsigned int sequence;
-} drm_i915_vblank_swap_t;
-
-typedef struct drm_i915_hws_addr {
-	__u64 addr;
-} drm_i915_hws_addr_t;
-
-struct drm_i915_gem_init {
-	/**
-	 * Beginning offset in the GTT to be managed by the DRM memory
-	 * manager.
-	 */
-	__u64 gtt_start;
-	/**
-	 * Ending offset in the GTT to be managed by the DRM memory
-	 * manager.
-	 */
-	__u64 gtt_end;
-};
-
-struct drm_i915_gem_create {
-	/**
-	 * Requested size for the object.
-	 *
-	 * The (page-aligned) allocated size for the object will be returned.
-	 */
-	__u64 size;
-	/**
-	 * Returned handle for the object.
-	 *
-	 * Object handles are nonzero.
-	 */
-	__u32 handle;
-	__u32 pad;
-};
-
-struct drm_i915_gem_create_ext {
-	/**
-	 * Requested size for the object.
-	 *
-	 * The (page-aligned) allocated size for the object will be returned.
-	 */
-	__u64 size;
-	/**
-	 * Returned handle for the object.
-	 *
-	 * Object handles are nonzero.
-	 */
-	__u32 handle;
-	__u32 pad;
-#define I915_GEM_CREATE_EXT_SETPARAM (1u << 0)
-#define I915_GEM_CREATE_EXT_FLAGS_UNKNOWN \
-	(-(I915_GEM_CREATE_EXT_SETPARAM << 1))
-	__u64 extensions;
-
-};
-
-struct drm_i915_gem_pread {
-	/** Handle for the object being read. */
-	__u32 handle;
-	__u32 pad;
-	/** Offset into the object to read from */
-	__u64 offset;
-	/** Length of data to read */
-	__u64 size;
-	/**
-	 * Pointer to write the data into.
-	 *
-	 * This is a fixed-size type for 32/64 compatibility.
-	 */
-	__u64 data_ptr;
-};
-
-struct drm_i915_gem_pwrite {
-	/** Handle for the object being written to. */
-	__u32 handle;
-	__u32 pad;
-	/** Offset into the object to write to */
-	__u64 offset;
-	/** Length of data to write */
-	__u64 size;
-	/**
-	 * Pointer to read the data from.
-	 *
-	 * This is a fixed-size type for 32/64 compatibility.
-	 */
-	__u64 data_ptr;
-};
-
-struct drm_i915_gem_mmap {
-	/** Handle for the object being mapped. */
-	__u32 handle;
-	__u32 pad;
-	/** Offset in the object to map. */
-	__u64 offset;
-	/**
-	 * Length of data to map.
-	 *
-	 * The value will be page-aligned.
-	 */
-	__u64 size;
-	/**
-	 * Returned pointer the data was mapped at.
-	 *
-	 * This is a fixed-size type for 32/64 compatibility.
-	 */
-	__u64 addr_ptr;
-
-	/**
-	 * Flags for extended behaviour.
-	 *
-	 * Added in version 2.
-	 */
-	__u64 flags;
-#define I915_MMAP_WC 0x1
-};
-
-struct drm_i915_gem_mmap_gtt {
-	/** Handle for the object being mapped. */
-	__u32 handle;
-	__u32 pad;
-	/**
-	 * Fake offset to use for subsequent mmap call
-	 *
-	 * This is a fixed-size type for 32/64 compatibility.
-	 */
-	__u64 offset;
-};
-
-struct drm_i915_gem_mmap_offset {
-	/** Handle for the object being mapped. */
-	__u32 handle;
-	__u32 pad;
-	/**
-	 * Fake offset to use for subsequent mmap call
-	 *
-	 * This is a fixed-size type for 32/64 compatibility.
-	 */
-	__u64 offset;
-
-	/**
-	 * Flags for extended behaviour.
-	 *
-	 * It is mandatory that one of the MMAP_OFFSET types
-	 * (GTT, WC, WB, UC, etc) should be included.
-	 */
-	__u64 flags;
-#define I915_MMAP_OFFSET_GTT 0
-#define I915_MMAP_OFFSET_WC  1
-#define I915_MMAP_OFFSET_WB  2
-#define I915_MMAP_OFFSET_UC  3
-
-	/*
-	 * Zero-terminated chain of extensions.
-	 *
-	 * No current extensions defined; mbz.
-	 */
-	__u64 extensions;
-};
-
-struct drm_i915_gem_set_domain {
-	/** Handle for the object */
-	__u32 handle;
-
-	/** New read domains */
-	__u32 read_domains;
-
-	/** New write domain */
-	__u32 write_domain;
-};
-
-struct drm_i915_gem_sw_finish {
-	/** Handle for the object */
-	__u32 handle;
-};
-
-struct drm_i915_gem_relocation_entry {
-	/**
-	 * Handle of the buffer being pointed to by this relocation entry.
-	 *
-	 * It's appealing to make this be an index into the mm_validate_entry
-	 * list to refer to the buffer, but this allows the driver to create
-	 * a relocation list for state buffers and not re-write it per
-	 * exec using the buffer.
-	 */
-	__u32 target_handle;
-
-	/**
-	 * Value to be added to the offset of the target buffer to make up
-	 * the relocation entry.
-	 */
-	__u32 delta;
-
-	/** Offset in the buffer the relocation entry will be written into */
-	__u64 offset;
-
-	/**
-	 * Offset value of the target buffer that the relocation entry was last
-	 * written as.
-	 *
-	 * If the buffer has the same offset as last time, we can skip syncing
-	 * and writing the relocation.  This value is written back out by
-	 * the execbuffer ioctl when the relocation is written.
-	 */
-	__u64 presumed_offset;
-
-	/**
-	 * Target memory domains read by this operation.
-	 */
-	__u32 read_domains;
-
-	/**
-	 * Target memory domains written by this operation.
-	 *
-	 * Note that only one domain may be written by the whole
-	 * execbuffer operation, so that where there are conflicts,
-	 * the application will get -EINVAL back.
-	 */
-	__u32 write_domain;
-};
-
-/** @{
- * Intel memory domains
- *
- * Most of these just align with the various caches in
- * the system and are used to flush and invalidate as
- * objects end up cached in different domains.
- */
-/** CPU cache */
-#define I915_GEM_DOMAIN_CPU		0x00000001
-/** Render cache, used by 2D and 3D drawing */
-#define I915_GEM_DOMAIN_RENDER		0x00000002
-/** Sampler cache, used by texture engine */
-#define I915_GEM_DOMAIN_SAMPLER		0x00000004
-/** Command queue, used to load batch buffers */
-#define I915_GEM_DOMAIN_COMMAND		0x00000008
-/** Instruction cache, used by shader programs */
-#define I915_GEM_DOMAIN_INSTRUCTION	0x00000010
-/** Vertex address cache */
-#define I915_GEM_DOMAIN_VERTEX		0x00000020
-/** GTT domain - aperture and scanout */
-#define I915_GEM_DOMAIN_GTT		0x00000040
-/** WC domain - uncached access */
-#define I915_GEM_DOMAIN_WC		0x00000080
-/** @} */
-
-struct drm_i915_gem_exec_object {
-	/**
-	 * User's handle for a buffer to be bound into the GTT for this
-	 * operation.
-	 */
-	__u32 handle;
-
-	/** Number of relocations to be performed on this buffer */
-	__u32 relocation_count;
-	/**
-	 * Pointer to array of struct drm_i915_gem_relocation_entry containing
-	 * the relocations to be performed in this buffer.
-	 */
-	__u64 relocs_ptr;
-
-	/** Required alignment in graphics aperture */
-	__u64 alignment;
-
-	/**
-	 * Returned value of the updated offset of the object, for future
-	 * presumed_offset writes.
-	 */
-	__u64 offset;
-};
-
-struct drm_i915_gem_execbuffer {
-	/**
-	 * List of buffers to be validated with their relocations to be
-	 * performend on them.
-	 *
-	 * This is a pointer to an array of struct drm_i915_gem_validate_entry.
-	 *
-	 * These buffers must be listed in an order such that all relocations
-	 * a buffer is performing refer to buffers that have already appeared
-	 * in the validate list.
-	 */
-	__u64 buffers_ptr;
-	__u32 buffer_count;
-
-	/** Offset in the batchbuffer to start execution from. */
-	__u32 batch_start_offset;
-	/** Bytes used in batchbuffer from batch_start_offset */
-	__u32 batch_len;
-	__u32 DR1;
-	__u32 DR4;
-	__u32 num_cliprects;
-	/** This is a struct drm_clip_rect *cliprects */
-	__u64 cliprects_ptr;
-};
-
-struct drm_i915_gem_exec_object2 {
-	/**
-	 * User's handle for a buffer to be bound into the GTT for this
-	 * operation.
-	 */
-	__u32 handle;
-
-	/** Number of relocations to be performed on this buffer */
-	__u32 relocation_count;
-	/**
-	 * Pointer to array of struct drm_i915_gem_relocation_entry containing
-	 * the relocations to be performed in this buffer.
-	 */
-	__u64 relocs_ptr;
-
-	/** Required alignment in graphics aperture */
-	__u64 alignment;
-
-	/**
-	 * When the EXEC_OBJECT_PINNED flag is specified this is populated by
-	 * the user with the GTT offset at which this object will be pinned.
-	 * When the I915_EXEC_NO_RELOC flag is specified this must contain the
-	 * presumed_offset of the object.
-	 * During execbuffer2 the kernel populates it with the value of the
-	 * current GTT offset of the object, for future presumed_offset writes.
-	 */
-	__u64 offset;
-
-#define EXEC_OBJECT_NEEDS_FENCE		 (1<<0)
-#define EXEC_OBJECT_NEEDS_GTT		 (1<<1)
-#define EXEC_OBJECT_WRITE		 (1<<2)
-#define EXEC_OBJECT_SUPPORTS_48B_ADDRESS (1<<3)
-#define EXEC_OBJECT_PINNED		 (1<<4)
-#define EXEC_OBJECT_PAD_TO_SIZE		 (1<<5)
-/* The kernel implicitly tracks GPU activity on all GEM objects, and
- * synchronises operations with outstanding rendering. This includes
- * rendering on other devices if exported via dma-buf. However, sometimes
- * this tracking is too coarse and the user knows better. For example,
- * if the object is split into non-overlapping ranges shared between different
- * clients or engines (i.e. suballocating objects), the implicit tracking
- * by kernel assumes that each operation affects the whole object rather
- * than an individual range, causing needless synchronisation between clients.
- * The kernel will also forgo any CPU cache flushes prior to rendering from
- * the object as the client is expected to be also handling such domain
- * tracking.
- *
- * The kernel maintains the implicit tracking in order to manage resources
- * used by the GPU - this flag only disables the synchronisation prior to
- * rendering with this object in this execbuf.
- *
- * Opting out of implicit synhronisation requires the user to do its own
- * explicit tracking to avoid rendering corruption. See, for example,
- * I915_PARAM_HAS_EXEC_FENCE to order execbufs and execute them asynchronously.
- */
-#define EXEC_OBJECT_ASYNC		(1<<6)
-/* Request that the contents of this execobject be copied into the error
- * state upon a GPU hang involving this batch for post-mortem debugging.
- * These buffers are recorded in no particular order as "user" in
- * /sys/class/drm/cardN/error. Query I915_PARAM_HAS_EXEC_CAPTURE to see
- * if the kernel supports this flag.
- */
-#define EXEC_OBJECT_CAPTURE		(1<<7)
-/* All remaining bits are MBZ and RESERVED FOR FUTURE USE */
-#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_CAPTURE<<1)
-	__u64 flags;
-
-	union {
-		__u64 rsvd1;
-		__u64 pad_to_size;
-	};
-	__u64 rsvd2;
-};
-
-struct drm_i915_gem_exec_fence {
-	/**
-	 * User's handle for a drm_syncobj to wait on or signal.
-	 */
-	__u32 handle;
-
-#define I915_EXEC_FENCE_WAIT            (1<<0)
-#define I915_EXEC_FENCE_SIGNAL          (1<<1)
-#define __I915_EXEC_FENCE_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SIGNAL << 1))
-	__u32 flags;
-};
-
-struct drm_i915_gem_execbuffer2 {
-	/**
-	 * List of gem_exec_object2 structs
-	 */
-	__u64 buffers_ptr;
-	__u32 buffer_count;
-
-	/** Offset in the batchbuffer to start execution from. */
-	__u32 batch_start_offset;
-	/** Bytes used in batchbuffer from batch_start_offset */
-	__u32 batch_len;
-	__u32 DR1;
-	__u32 DR4;
-	__u32 num_cliprects;
-	/**
-	 * This is a struct drm_clip_rect *cliprects if I915_EXEC_FENCE_ARRAY
-	 * is not set.  If I915_EXEC_FENCE_ARRAY is set, then this is a
-	 * struct drm_i915_gem_exec_fence *fences.
-	 */
-	__u64 cliprects_ptr;
-#define I915_EXEC_RING_MASK              (0x3f)
-#define I915_EXEC_DEFAULT                (0<<0)
-#define I915_EXEC_RENDER                 (1<<0)
-#define I915_EXEC_BSD                    (2<<0)
-#define I915_EXEC_BLT                    (3<<0)
-#define I915_EXEC_VEBOX                  (4<<0)
-
-/* Used for switching the constants addressing mode on gen4+ RENDER ring.
- * Gen6+ only supports relative addressing to dynamic state (default) and
- * absolute addressing.
- *
- * These flags are ignored for the BSD and BLT rings.
- */
-#define I915_EXEC_CONSTANTS_MASK 	(3<<6)
-#define I915_EXEC_CONSTANTS_REL_GENERAL (0<<6) /* default */
-#define I915_EXEC_CONSTANTS_ABSOLUTE 	(1<<6)
-#define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */
-	__u64 flags;
-	__u64 rsvd1; /* now used for context info */
-	__u64 rsvd2;
-};
-
-/** Resets the SO write offset registers for transform feedback on gen7. */
-#define I915_EXEC_GEN7_SOL_RESET	(1<<8)
-
-/** Request a privileged ("secure") batch buffer. Note only available for
- * DRM_ROOT_ONLY | DRM_MASTER processes.
- */
-#define I915_EXEC_SECURE		(1<<9)
-
-/** Inform the kernel that the batch is and will always be pinned. This
- * negates the requirement for a workaround to be performed to avoid
- * an incoherent CS (such as can be found on 830/845). If this flag is
- * not passed, the kernel will endeavour to make sure the batch is
- * coherent with the CS before execution. If this flag is passed,
- * userspace assumes the responsibility for ensuring the same.
- */
-#define I915_EXEC_IS_PINNED		(1<<10)
-
-/** Provide a hint to the kernel that the command stream and auxiliary
- * state buffers already holds the correct presumed addresses and so the
- * relocation process may be skipped if no buffers need to be moved in
- * preparation for the execbuffer.
- */
-#define I915_EXEC_NO_RELOC		(1<<11)
-
-/** Use the reloc.handle as an index into the exec object array rather
- * than as the per-file handle.
- */
-#define I915_EXEC_HANDLE_LUT		(1<<12)
-
-/** Used for switching BSD rings on the platforms with two BSD rings */
-#define I915_EXEC_BSD_SHIFT	 (13)
-#define I915_EXEC_BSD_MASK	 (3 << I915_EXEC_BSD_SHIFT)
-/* default ping-pong mode */
-#define I915_EXEC_BSD_DEFAULT	 (0 << I915_EXEC_BSD_SHIFT)
-#define I915_EXEC_BSD_RING1	 (1 << I915_EXEC_BSD_SHIFT)
-#define I915_EXEC_BSD_RING2	 (2 << I915_EXEC_BSD_SHIFT)
-
-/** Tell the kernel that the batchbuffer is processed by
- *  the resource streamer.
- */
-#define I915_EXEC_RESOURCE_STREAMER     (1<<15)
-
-/* Setting I915_EXEC_FENCE_IN implies that lower_32_bits(rsvd2) represent
- * a sync_file fd to wait upon (in a nonblocking manner) prior to executing
- * the batch.
- *
- * Returns -EINVAL if the sync_file fd cannot be found.
- */
-#define I915_EXEC_FENCE_IN		(1<<16)
-
-/* Setting I915_EXEC_FENCE_OUT causes the ioctl to return a sync_file fd
- * in the upper_32_bits(rsvd2) upon success. Ownership of the fd is given
- * to the caller, and it should be close() after use. (The fd is a regular
- * file descriptor and will be cleaned up on process termination. It holds
- * a reference to the request, but nothing else.)
- *
- * The sync_file fd can be combined with other sync_file and passed either
- * to execbuf using I915_EXEC_FENCE_IN, to atomic KMS ioctls (so that a flip
- * will only occur after this request completes), or to other devices.
- *
- * Using I915_EXEC_FENCE_OUT requires use of
- * DRM_IOCTL_I915_GEM_EXECBUFFER2_WR ioctl so that the result is written
- * back to userspace. Failure to do so will cause the out-fence to always
- * be reported as zero, and the real fence fd to be leaked.
- */
-#define I915_EXEC_FENCE_OUT		(1<<17)
-
-/*
- * Traditionally the execbuf ioctl has only considered the final element in
- * the execobject[] to be the executable batch. Often though, the client
- * will known the batch object prior to construction and being able to place
- * it into the execobject[] array first can simplify the relocation tracking.
- * Setting I915_EXEC_BATCH_FIRST tells execbuf to use element 0 of the
- * execobject[] as the * batch instead (the default is to use the last
- * element).
- */
-#define I915_EXEC_BATCH_FIRST		(1<<18)
-
-/* Setting I915_FENCE_ARRAY implies that num_cliprects and cliprects_ptr
- * define an array of i915_gem_exec_fence structures which specify a set of
- * dma fences to wait upon or signal.
- */
-#define I915_EXEC_FENCE_ARRAY   (1<<19)
-
-/*
- * Setting I915_EXEC_FENCE_SUBMIT implies that lower_32_bits(rsvd2) represent
- * a sync_file fd to wait upon (in a nonblocking manner) prior to executing
- * the batch.
- *
- * Returns -EINVAL if the sync_file fd cannot be found.
- */
-#define I915_EXEC_FENCE_SUBMIT		(1 << 20)
-
-#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SUBMIT << 1))
-
-#define I915_EXEC_CONTEXT_ID_MASK	(0xffffffff)
-#define i915_execbuffer2_set_context_id(eb2, context) \
-	(eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK
-#define i915_execbuffer2_get_context_id(eb2) \
-	((eb2).rsvd1 & I915_EXEC_CONTEXT_ID_MASK)
-
-struct drm_i915_gem_pin {
-	/** Handle of the buffer to be pinned. */
-	__u32 handle;
-	__u32 pad;
-
-	/** alignment required within the aperture */
-	__u64 alignment;
-
-	/** Returned GTT offset of the buffer. */
-	__u64 offset;
-};
-
-struct drm_i915_gem_unpin {
-	/** Handle of the buffer to be unpinned. */
-	__u32 handle;
-	__u32 pad;
-};
-
-struct drm_i915_gem_busy {
-	/** Handle of the buffer to check for busy */
-	__u32 handle;
-
-	/** Return busy status
-	 *
-	 * A return of 0 implies that the object is idle (after
-	 * having flushed any pending activity), and a non-zero return that
-	 * the object is still in-flight on the GPU. (The GPU has not yet
-	 * signaled completion for all pending requests that reference the
-	 * object.) An object is guaranteed to become idle eventually (so
-	 * long as no new GPU commands are executed upon it). Due to the
-	 * asynchronous nature of the hardware, an object reported
-	 * as busy may become idle before the ioctl is completed.
-	 *
-	 * Furthermore, if the object is busy, which engine is busy is only
-	 * provided as a guide and only indirectly by reporting its class
-	 * (there may be more than one engine in each class). There are race
-	 * conditions which prevent the report of which engines are busy from
-	 * being always accurate.  However, the converse is not true. If the
-	 * object is idle, the result of the ioctl, that all engines are idle,
-	 * is accurate.
-	 *
-	 * The returned dword is split into two fields to indicate both
-	 * the engine classess on which the object is being read, and the
-	 * engine class on which it is currently being written (if any).
-	 *
-	 * The low word (bits 0:15) indicate if the object is being written
-	 * to by any engine (there can only be one, as the GEM implicit
-	 * synchronisation rules force writes to be serialised). Only the
-	 * engine class (offset by 1, I915_ENGINE_CLASS_RENDER is reported as
-	 * 1 not 0 etc) for the last write is reported.
-	 *
-	 * The high word (bits 16:31) are a bitmask of which engines classes
-	 * are currently reading from the object. Multiple engines may be
-	 * reading from the object simultaneously.
-	 *
-	 * The value of each engine class is the same as specified in the
-	 * I915_CONTEXT_SET_ENGINES parameter and via perf, i.e.
-	 * I915_ENGINE_CLASS_RENDER, I915_ENGINE_CLASS_COPY, etc.
-	 * reported as active itself. Some hardware may have parallel
-	 * execution engines, e.g. multiple media engines, which are
-	 * mapped to the same class identifier and so are not separately
-	 * reported for busyness.
-	 *
-	 * Caveat emptor:
-	 * Only the boolean result of this query is reliable; that is whether
-	 * the object is idle or busy. The report of which engines are busy
-	 * should be only used as a heuristic.
-	 */
-	__u32 busy;
-};
-
-/**
- * I915_CACHING_NONE
- *
- * GPU access is not coherent with cpu caches. Default for machines without an
- * LLC.
- */
-#define I915_CACHING_NONE		0
-/**
- * I915_CACHING_CACHED
- *
- * GPU access is coherent with cpu caches and furthermore the data is cached in
- * last-level caches shared between cpu cores and the gpu GT. Default on
- * machines with HAS_LLC.
- */
-#define I915_CACHING_CACHED		1
-/**
- * I915_CACHING_DISPLAY
- *
- * Special GPU caching mode which is coherent with the scanout engines.
- * Transparently falls back to I915_CACHING_NONE on platforms where no special
- * cache mode (like write-through or gfdt flushing) is available. The kernel
- * automatically sets this mode when using a buffer as a scanout target.
- * Userspace can manually set this mode to avoid a costly stall and clflush in
- * the hotpath of drawing the first frame.
- */
-#define I915_CACHING_DISPLAY		2
-
-struct drm_i915_gem_caching {
-	/**
-	 * Handle of the buffer to set/get the caching level of. */
-	__u32 handle;
-
-	/**
-	 * Cacheing level to apply or return value
-	 *
-	 * bits0-15 are for generic caching control (i.e. the above defined
-	 * values). bits16-31 are reserved for platform-specific variations
-	 * (e.g. l3$ caching on gen7). */
-	__u32 caching;
-};
-
-#define I915_TILING_NONE	0
-#define I915_TILING_X		1
-#define I915_TILING_Y		2
-#define I915_TILING_LAST	I915_TILING_Y
-
-#define I915_BIT_6_SWIZZLE_NONE		0
-#define I915_BIT_6_SWIZZLE_9		1
-#define I915_BIT_6_SWIZZLE_9_10		2
-#define I915_BIT_6_SWIZZLE_9_11		3
-#define I915_BIT_6_SWIZZLE_9_10_11	4
-/* Not seen by userland */
-#define I915_BIT_6_SWIZZLE_UNKNOWN	5
-/* Seen by userland. */
-#define I915_BIT_6_SWIZZLE_9_17		6
-#define I915_BIT_6_SWIZZLE_9_10_17	7
-
-struct drm_i915_gem_set_tiling {
-	/** Handle of the buffer to have its tiling state updated */
-	__u32 handle;
-
-	/**
-	 * Tiling mode for the object (I915_TILING_NONE, I915_TILING_X,
-	 * I915_TILING_Y).
-	 *
-	 * This value is to be set on request, and will be updated by the
-	 * kernel on successful return with the actual chosen tiling layout.
-	 *
-	 * The tiling mode may be demoted to I915_TILING_NONE when the system
-	 * has bit 6 swizzling that can't be managed correctly by GEM.
-	 *
-	 * Buffer contents become undefined when changing tiling_mode.
-	 */
-	__u32 tiling_mode;
-
-	/**
-	 * Stride in bytes for the object when in I915_TILING_X or
-	 * I915_TILING_Y.
-	 */
-	__u32 stride;
-
-	/**
-	 * Returned address bit 6 swizzling required for CPU access through
-	 * mmap mapping.
-	 */
-	__u32 swizzle_mode;
-};
-
-struct drm_i915_gem_get_tiling {
-	/** Handle of the buffer to get tiling state for. */
-	__u32 handle;
-
-	/**
-	 * Current tiling mode for the object (I915_TILING_NONE, I915_TILING_X,
-	 * I915_TILING_Y).
-	 */
-	__u32 tiling_mode;
-
-	/**
-	 * Returned address bit 6 swizzling required for CPU access through
-	 * mmap mapping.
-	 */
-	__u32 swizzle_mode;
-
-	/**
-	 * Returned address bit 6 swizzling required for CPU access through
-	 * mmap mapping whilst bound.
-	 */
-	__u32 phys_swizzle_mode;
-};
-
-struct drm_i915_gem_get_aperture {
-	/** Total size of the aperture used by i915_gem_execbuffer, in bytes */
-	__u64 aper_size;
-
-	/**
-	 * Available space in the aperture used by i915_gem_execbuffer, in
-	 * bytes
-	 */
-	__u64 aper_available_size;
-};
-
-struct drm_i915_get_pipe_from_crtc_id {
-	/** ID of CRTC being requested **/
-	__u32 crtc_id;
-
-	/** pipe of requested CRTC **/
-	__u32 pipe;
-};
-
-#define I915_MADV_WILLNEED 0
-#define I915_MADV_DONTNEED 1
-#define __I915_MADV_PURGED 2 /* internal state */
-
-struct drm_i915_gem_madvise {
-	/** Handle of the buffer to change the backing store advice */
-	__u32 handle;
-
-	/* Advice: either the buffer will be needed again in the near future,
-	 *         or wont be and could be discarded under memory pressure.
-	 */
-	__u32 madv;
-
-	/** Whether the backing store still exists. */
-	__u32 retained;
-};
-
-/* flags */
-#define I915_OVERLAY_TYPE_MASK 		0xff
-#define I915_OVERLAY_YUV_PLANAR 	0x01
-#define I915_OVERLAY_YUV_PACKED 	0x02
-#define I915_OVERLAY_RGB		0x03
-
-#define I915_OVERLAY_DEPTH_MASK		0xff00
-#define I915_OVERLAY_RGB24		0x1000
-#define I915_OVERLAY_RGB16		0x2000
-#define I915_OVERLAY_RGB15		0x3000
-#define I915_OVERLAY_YUV422		0x0100
-#define I915_OVERLAY_YUV411		0x0200
-#define I915_OVERLAY_YUV420		0x0300
-#define I915_OVERLAY_YUV410		0x0400
-
-#define I915_OVERLAY_SWAP_MASK		0xff0000
-#define I915_OVERLAY_NO_SWAP		0x000000
-#define I915_OVERLAY_UV_SWAP		0x010000
-#define I915_OVERLAY_Y_SWAP		0x020000
-#define I915_OVERLAY_Y_AND_UV_SWAP	0x030000
-
-#define I915_OVERLAY_FLAGS_MASK		0xff000000
-#define I915_OVERLAY_ENABLE		0x01000000
-
-struct drm_intel_overlay_put_image {
-	/* various flags and src format description */
-	__u32 flags;
-	/* source picture description */
-	__u32 bo_handle;
-	/* stride values and offsets are in bytes, buffer relative */
-	__u16 stride_Y; /* stride for packed formats */
-	__u16 stride_UV;
-	__u32 offset_Y; /* offset for packet formats */
-	__u32 offset_U;
-	__u32 offset_V;
-	/* in pixels */
-	__u16 src_width;
-	__u16 src_height;
-	/* to compensate the scaling factors for partially covered surfaces */
-	__u16 src_scan_width;
-	__u16 src_scan_height;
-	/* output crtc description */
-	__u32 crtc_id;
-	__u16 dst_x;
-	__u16 dst_y;
-	__u16 dst_width;
-	__u16 dst_height;
-};
-
-/* flags */
-#define I915_OVERLAY_UPDATE_ATTRS	(1<<0)
-#define I915_OVERLAY_UPDATE_GAMMA	(1<<1)
-#define I915_OVERLAY_DISABLE_DEST_COLORKEY	(1<<2)
-struct drm_intel_overlay_attrs {
-	__u32 flags;
-	__u32 color_key;
-	__s32 brightness;
-	__u32 contrast;
-	__u32 saturation;
-	__u32 gamma0;
-	__u32 gamma1;
-	__u32 gamma2;
-	__u32 gamma3;
-	__u32 gamma4;
-	__u32 gamma5;
-};
-
-/*
- * Intel sprite handling
- *
- * Color keying works with a min/mask/max tuple.  Both source and destination
- * color keying is allowed.
- *
- * Source keying:
- * Sprite pixels within the min & max values, masked against the color channels
- * specified in the mask field, will be transparent.  All other pixels will
- * be displayed on top of the primary plane.  For RGB surfaces, only the min
- * and mask fields will be used; ranged compares are not allowed.
- *
- * Destination keying:
- * Primary plane pixels that match the min value, masked against the color
- * channels specified in the mask field, will be replaced by corresponding
- * pixels from the sprite plane.
- *
- * Note that source & destination keying are exclusive; only one can be
- * active on a given plane.
- */
-
-#define I915_SET_COLORKEY_NONE		(1<<0) /* Deprecated. Instead set
-						* flags==0 to disable colorkeying.
-						*/
-#define I915_SET_COLORKEY_DESTINATION	(1<<1)
-#define I915_SET_COLORKEY_SOURCE	(1<<2)
-struct drm_intel_sprite_colorkey {
-	__u32 plane_id;
-	__u32 min_value;
-	__u32 channel_mask;
-	__u32 max_value;
-	__u32 flags;
-};
-
-struct drm_i915_gem_wait {
-	/** Handle of BO we shall wait on */
-	__u32 bo_handle;
-	__u32 flags;
-	/** Number of nanoseconds to wait, Returns time remaining. */
-	__s64 timeout_ns;
-};
-
-struct drm_i915_gem_context_create {
-	__u32 ctx_id; /* output: id of new context*/
-	__u32 pad;
-};
-
-struct drm_i915_gem_context_create_ext {
-	__u32 ctx_id; /* output: id of new context*/
-	__u32 flags;
-#define I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS	(1u << 0)
-#define I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE	(1u << 1)
-#define I915_CONTEXT_CREATE_FLAGS_UNKNOWN \
-	(-(I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE << 1))
-	__u64 extensions;
-};
-
-struct drm_i915_gem_context_param {
-	__u32 ctx_id;
-	__u32 size;
-	__u64 param;
-#define I915_CONTEXT_PARAM_BAN_PERIOD	0x1
-#define I915_CONTEXT_PARAM_NO_ZEROMAP	0x2
-#define I915_CONTEXT_PARAM_GTT_SIZE	0x3
-#define I915_CONTEXT_PARAM_NO_ERROR_CAPTURE	0x4
-#define I915_CONTEXT_PARAM_BANNABLE	0x5
-#define I915_CONTEXT_PARAM_PRIORITY	0x6
-#define   I915_CONTEXT_MAX_USER_PRIORITY	1023 /* inclusive */
-#define   I915_CONTEXT_DEFAULT_PRIORITY		0
-#define   I915_CONTEXT_MIN_USER_PRIORITY	-1023 /* inclusive */
-	/*
-	 * When using the following param, value should be a pointer to
-	 * drm_i915_gem_context_param_sseu.
-	 */
-#define I915_CONTEXT_PARAM_SSEU		0x7
-
-/*
- * Not all clients may want to attempt automatic recover of a context after
- * a hang (for example, some clients may only submit very small incremental
- * batches relying on known logical state of previous batches which will never
- * recover correctly and each attempt will hang), and so would prefer that
- * the context is forever banned instead.
- *
- * If set to false (0), after a reset, subsequent (and in flight) rendering
- * from this context is discarded, and the client will need to create a new
- * context to use instead.
- *
- * If set to true (1), the kernel will automatically attempt to recover the
- * context by skipping the hanging batch and executing the next batch starting
- * from the default context state (discarding the incomplete logical context
- * state lost due to the reset).
- *
- * On creation, all new contexts are marked as recoverable.
- */
-#define I915_CONTEXT_PARAM_RECOVERABLE	0x8
-
-	/*
-	 * The id of the associated virtual memory address space (ppGTT) of
-	 * this context. Can be retrieved and passed to another context
-	 * (on the same fd) for both to use the same ppGTT and so share
-	 * address layouts, and avoid reloading the page tables on context
-	 * switches between themselves.
-	 *
-	 * See DRM_I915_GEM_VM_CREATE and DRM_I915_GEM_VM_DESTROY.
-	 */
-#define I915_CONTEXT_PARAM_VM		0x9
-
-/*
- * I915_CONTEXT_PARAM_ENGINES:
- *
- * Bind this context to operate on this subset of available engines. Henceforth,
- * the I915_EXEC_RING selector for DRM_IOCTL_I915_GEM_EXECBUFFER2 operates as
- * an index into this array of engines; I915_EXEC_DEFAULT selecting engine[0]
- * and upwards. Slots 0...N are filled in using the specified (class, instance).
- * Use
- *	engine_class: I915_ENGINE_CLASS_INVALID,
- *	engine_instance: I915_ENGINE_CLASS_INVALID_NONE
- * to specify a gap in the array that can be filled in later, e.g. by a
- * virtual engine used for load balancing.
- *
- * Setting the number of engines bound to the context to 0, by passing a zero
- * sized argument, will revert back to default settings.
- *
- * See struct i915_context_param_engines.
- *
- * Extensions:
- *   i915_context_engines_load_balance (I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE)
- *   i915_context_engines_bond (I915_CONTEXT_ENGINES_EXT_BOND)
- */
-#define I915_CONTEXT_PARAM_ENGINES	0xa
-
-/*
- * I915_CONTEXT_PARAM_PERSISTENCE:
- *
- * Allow the context and active rendering to survive the process until
- * completion. Persistence allows fire-and-forget clients to queue up a
- * bunch of work, hand the output over to a display server and then quit.
- * If the context is marked as not persistent, upon closing (either via
- * an explicit DRM_I915_GEM_CONTEXT_DESTROY or implicitly from file closure
- * or process termination), the context and any outstanding requests will be
- * cancelled (and exported fences for cancelled requests marked as -EIO).
- *
- * By default, new contexts allow persistence.
- */
-#define I915_CONTEXT_PARAM_PERSISTENCE	0xb
-
-/*
- * I915_CONTEXT_PARAM_PROTECTED_CONTENT:
- *
- * If set to true (1) PAVP content protection is enabled.
- * When enabled, the context is marked unrecoverable and may
- * become invalid due to PAVP teardown event or other error.
- */
-#define I915_CONTEXT_PARAM_PROTECTED_CONTENT    0xd
-/* Must be kept compact -- no holes and well documented */
-
-	__u64 value;
-};
-
-struct drm_i915_gem_object_param {
-	/* Object handle (0 for I915_GEM_CREATE_EXT_SETPARAM) */
-	__u32 handle;
-
-	/* Data pointer size */
-	__u32 size;
-
-/*
- * I915_OBJECT_PARAM:
- *
- * Select object namespace for the param.
- */
-#define I915_OBJECT_PARAM  (1ull<<32)
-
-/*
- * I915_PARAM_PROTECTED_CONTENT:
- *
- * If set to true (1) buffer contents is expected to be protected by
- * PAVP encryption and requires decryption for scan out and processing.
- * Protected buffers can only be used in PAVP protected contexts.
- * A protected buffer may become invalid as a result of PAVP teardown.
- */
-#define I915_PARAM_PROTECTED_CONTENT  0x1
-
-	__u64 param;
-
-	/* Data value or pointer */
-	__u64 data;
-};
-
-struct drm_i915_gem_create_ext_setparam {
-	struct i915_user_extension base;
-	struct drm_i915_gem_object_param param;
-};
-
-/**
- * Context SSEU programming
- *
- * It may be necessary for either functional or performance reason to configure
- * a context to run with a reduced number of SSEU (where SSEU stands for Slice/
- * Sub-slice/EU).
- *
- * This is done by configuring SSEU configuration using the below
- * @struct drm_i915_gem_context_param_sseu for every supported engine which
- * userspace intends to use.
- *
- * Not all GPUs or engines support this functionality in which case an error
- * code -ENODEV will be returned.
- *
- * Also, flexibility of possible SSEU configuration permutations varies between
- * GPU generations and software imposed limitations. Requesting such a
- * combination will return an error code of -EINVAL.
- *
- * NOTE: When perf/OA is active the context's SSEU configuration is ignored in
- * favour of a single global setting.
- */
-struct drm_i915_gem_context_param_sseu {
-	/*
-	 * Engine class & instance to be configured or queried.
-	 */
-	struct i915_engine_class_instance engine;
-
-	/*
-	 * Unknown flags must be cleared to zero.
-	 */
-	__u32 flags;
-#define I915_CONTEXT_SSEU_FLAG_ENGINE_INDEX (1u << 0)
-
-	/*
-	 * Mask of slices to enable for the context. Valid values are a subset
-	 * of the bitmask value returned for I915_PARAM_SLICE_MASK.
-	 */
-	__u64 slice_mask;
-
-	/*
-	 * Mask of subslices to enable for the context. Valid values are a
-	 * subset of the bitmask value return by I915_PARAM_SUBSLICE_MASK.
-	 */
-	__u64 subslice_mask;
-
-	/*
-	 * Minimum/Maximum number of EUs to enable per subslice for the
-	 * context. min_eus_per_subslice must be inferior or equal to
-	 * max_eus_per_subslice.
-	 */
-	__u16 min_eus_per_subslice;
-	__u16 max_eus_per_subslice;
-
-	/*
-	 * Unused for now. Must be cleared to zero.
-	 */
-	__u32 rsvd;
-};
-
-/*
- * i915_context_engines_load_balance:
- *
- * Enable load balancing across this set of engines.
- *
- * Into the I915_EXEC_DEFAULT slot [0], a virtual engine is created that when
- * used will proxy the execbuffer request onto one of the set of engines
- * in such a way as to distribute the load evenly across the set.
- *
- * The set of engines must be compatible (e.g. the same HW class) as they
- * will share the same logical GPU context and ring.
- *
- * To intermix rendering with the virtual engine and direct rendering onto
- * the backing engines (bypassing the load balancing proxy), the context must
- * be defined to use a single timeline for all engines.
- */
-struct i915_context_engines_load_balance {
-	struct i915_user_extension base;
-
-	__u16 engine_index;
-	__u16 num_siblings;
-	__u32 flags; /* all undefined flags must be zero */
-
-	__u64 mbz64; /* reserved for future use; must be zero */
-
-	struct i915_engine_class_instance engines[0];
-} __attribute__((packed));
-
-#define I915_DEFINE_CONTEXT_ENGINES_LOAD_BALANCE(name__, N__) struct { \
-	struct i915_user_extension base; \
-	__u16 engine_index; \
-	__u16 num_siblings; \
-	__u32 flags; \
-	__u64 mbz64; \
-	struct i915_engine_class_instance engines[N__]; \
-} __attribute__((packed)) name__
-
-/*
- * i915_context_engines_bond:
- *
- * Constructed bonded pairs for execution within a virtual engine.
- *
- * All engines are equal, but some are more equal than others. Given
- * the distribution of resources in the HW, it may be preferable to run
- * a request on a given subset of engines in parallel to a request on a
- * specific engine. We enable this selection of engines within a virtual
- * engine by specifying bonding pairs, for any given master engine we will
- * only execute on one of the corresponding siblings within the virtual engine.
- *
- * To execute a request in parallel on the master engine and a sibling requires
- * coordination with a I915_EXEC_FENCE_SUBMIT.
- */
-struct i915_context_engines_bond {
-	struct i915_user_extension base;
-
-	struct i915_engine_class_instance master;
-
-	__u16 virtual_index; /* index of virtual engine in ctx->engines[] */
-	__u16 num_bonds;
-
-	__u64 flags; /* all undefined flags must be zero */
-	__u64 mbz64[4]; /* reserved for future use; must be zero */
-
-	struct i915_engine_class_instance engines[0];
-} __attribute__((packed));
-
-#define I915_DEFINE_CONTEXT_ENGINES_BOND(name__, N__) struct { \
-	struct i915_user_extension base; \
-	struct i915_engine_class_instance master; \
-	__u16 virtual_index; \
-	__u16 num_bonds; \
-	__u64 flags; \
-	__u64 mbz64[4]; \
-	struct i915_engine_class_instance engines[N__]; \
-} __attribute__((packed)) name__
-
-struct i915_context_param_engines {
-	__u64 extensions; /* linked chain of extension blocks, 0 terminates */
-#define I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE 0 /* see i915_context_engines_load_balance */
-#define I915_CONTEXT_ENGINES_EXT_BOND 1 /* see i915_context_engines_bond */
-	struct i915_engine_class_instance engines[0];
-} __attribute__((packed));
-
-#define I915_DEFINE_CONTEXT_PARAM_ENGINES(name__, N__) struct { \
-	__u64 extensions; \
-	struct i915_engine_class_instance engines[N__]; \
-} __attribute__((packed)) name__
-
-struct drm_i915_gem_context_create_ext_setparam {
-#define I915_CONTEXT_CREATE_EXT_SETPARAM 0
-	struct i915_user_extension base;
-	struct drm_i915_gem_context_param param;
-};
-
-struct drm_i915_gem_context_create_ext_clone {
-#define I915_CONTEXT_CREATE_EXT_CLONE 1
-	struct i915_user_extension base;
-	__u32 clone_id;
-	__u32 flags;
-#define I915_CONTEXT_CLONE_ENGINES	(1u << 0)
-#define I915_CONTEXT_CLONE_FLAGS	(1u << 1)
-#define I915_CONTEXT_CLONE_SCHEDATTR	(1u << 2)
-#define I915_CONTEXT_CLONE_SSEU		(1u << 3)
-#define I915_CONTEXT_CLONE_TIMELINE	(1u << 4)
-#define I915_CONTEXT_CLONE_VM		(1u << 5)
-#define I915_CONTEXT_CLONE_UNKNOWN -(I915_CONTEXT_CLONE_VM << 1)
-	__u64 rsvd;
-};
-
-struct drm_i915_gem_context_destroy {
-	__u32 ctx_id;
-	__u32 pad;
-};
-
-/*
- * DRM_I915_GEM_VM_CREATE -
- *
- * Create a new virtual memory address space (ppGTT) for use within a context
- * on the same file. Extensions can be provided to configure exactly how the
- * address space is setup upon creation.
- *
- * The id of new VM (bound to the fd) for use with I915_CONTEXT_PARAM_VM is
- * returned in the outparam @id.
- *
- * No flags are defined, with all bits reserved and must be zero.
- *
- * An extension chain maybe provided, starting with @extensions, and terminated
- * by the @next_extension being 0. Currently, no extensions are defined.
- *
- * DRM_I915_GEM_VM_DESTROY -
- *
- * Destroys a previously created VM id, specified in @id.
- *
- * No extensions or flags are allowed currently, and so must be zero.
- */
-struct drm_i915_gem_vm_control {
-	__u64 extensions;
-	__u32 flags;
-	__u32 vm_id;
-};
-
-/*
- * struct pxp_sm_query_pxp_tag - Params to query the PXP tag of specified
- * session id and whether the session is alive from PXP state machine.
- */
-struct pxp_sm_query_pxp_tag {
-	__u32 session_is_alive;
-	__u32 pxp_tag; /* in  - Session ID, out pxp tag */
-};
-
-/*
- * struct pxp_set_session_status_params - Params to reserved, set or destroy
- * the session from the PXP state machine.
- */
-struct pxp_set_session_status_params {
-	__u32 pxp_tag; /* in [optional], for Arbitrator session, out pxp tag */
-	__u32 session_type; /* in, session type */
-	__u32 session_mode; /* in, session mode */
-	__u32 req_session_state; /* in, new session state */
-};
-
-/*
- * struct pxp_tee_io_message_params - Params to send/receive message to/from TEE.
- */
-struct pxp_tee_io_message_params {
-	__u8 *msg_in; /* in - message input */
-	__u32 msg_in_size; /* in - message input size */
-	__u8 *msg_out; /* in - message output buffer */
-	__u32 msg_out_size; /* out- message output size from TEE */
-	__u32 msg_out_buf_size; /* in - message output buffer size */
-};
-
-/*
- * struct pxp_info - Params for PXP operation.
- */
-struct pxp_info {
-	__u32 action; /* in - specified action of this operation */
-	__u32 sm_status; /* out - status output for this operation */
-
-	union {
-		/* in - action params to query PXP tag */
-		struct pxp_sm_query_pxp_tag query_pxp_tag;
-		/* in - action params to set the PXP session state */
-		struct pxp_set_session_status_params set_session_status;
-		/* in - action params to send TEE commands */
-		struct pxp_tee_io_message_params tee_io_message;
-
-		/* in - action params to set user space context */
-		__u32 set_user_ctx;
-	};
-} __attribute__((packed));
-
-/*
- * DRM_I915_PXP_OPS -
- *
- * PXP is an i915 componment, that helps user space to establish the hardware
- * protected session and manage the status of each alive software session,
- * as well as the life cycle of each session.
- *
- * This ioctl is to allow user space driver to create, set, and destroy each
- * session. It also provides the communication chanel to TEE (Trusted
- * Execution Environment) for the protected hardware session creation.
- */
-struct drm_i915_pxp_ops {
-	/* in - user space pointer to struct pxp_info */
-	struct pxp_info *info_ptr;
-
-	/* in - memory size that info_ptr points to */
-	__u32 info_size;
-};
-
-struct drm_i915_reg_read {
-	/*
-	 * Register offset.
-	 * For 64bit wide registers where the upper 32bits don't immediately
-	 * follow the lower 32bits, the offset of the lower 32bits must
-	 * be specified
-	 */
-	__u64 offset;
-#define I915_REG_READ_8B_WA (1ul << 0)
-
-	__u64 val; /* Return value */
-};
-
-/* Known registers:
- *
- * Render engine timestamp - 0x2358 + 64bit - gen7+
- * - Note this register returns an invalid value if using the default
- *   single instruction 8byte read, in order to workaround that pass
- *   flag I915_REG_READ_8B_WA in offset field.
- *
- */
-
-struct drm_i915_reset_stats {
-	__u32 ctx_id;
-	__u32 flags;
-
-	/* All resets since boot/module reload, for all contexts */
-	__u32 reset_count;
-
-	/* Number of batches lost when active in GPU, for this context */
-	__u32 batch_active;
-
-	/* Number of batches lost pending for execution, for this context */
-	__u32 batch_pending;
-
-	__u32 pad;
-};
-
-struct drm_i915_gem_userptr {
-	__u64 user_ptr;
-	__u64 user_size;
-	__u32 flags;
-#define I915_USERPTR_READ_ONLY 0x1
-#define I915_USERPTR_UNSYNCHRONIZED 0x80000000
-	/**
-	 * Returned handle for the object.
-	 *
-	 * Object handles are nonzero.
-	 */
-	__u32 handle;
-};
-
-enum drm_i915_oa_format {
-	I915_OA_FORMAT_A13 = 1,	    /* HSW only */
-	I915_OA_FORMAT_A29,	    /* HSW only */
-	I915_OA_FORMAT_A13_B8_C8,   /* HSW only */
-	I915_OA_FORMAT_B4_C8,	    /* HSW only */
-	I915_OA_FORMAT_A45_B8_C8,   /* HSW only */
-	I915_OA_FORMAT_B4_C8_A16,   /* HSW only */
-	I915_OA_FORMAT_C4_B8,	    /* HSW+ */
-
-	/* Gen8+ */
-	I915_OA_FORMAT_A12,
-	I915_OA_FORMAT_A12_B8_C8,
-	I915_OA_FORMAT_A32u40_A4u32_B8_C8,
-
-	I915_OA_FORMAT_MAX	    /* non-ABI */
-};
-
-enum drm_i915_perf_property_id {
-	/**
-	 * Open the stream for a specific context handle (as used with
-	 * execbuffer2). A stream opened for a specific context this way
-	 * won't typically require root privileges.
-	 *
-	 * This property is available in perf revision 1.
-	 */
-	DRM_I915_PERF_PROP_CTX_HANDLE = 1,
-
-	/**
-	 * A value of 1 requests the inclusion of raw OA unit reports as
-	 * part of stream samples.
-	 *
-	 * This property is available in perf revision 1.
-	 */
-	DRM_I915_PERF_PROP_SAMPLE_OA,
-
-	/**
-	 * The value specifies which set of OA unit metrics should be
-	 * be configured, defining the contents of any OA unit reports.
-	 *
-	 * This property is available in perf revision 1.
-	 */
-	DRM_I915_PERF_PROP_OA_METRICS_SET,
-
-	/**
-	 * The value specifies the size and layout of OA unit reports.
-	 *
-	 * This property is available in perf revision 1.
-	 */
-	DRM_I915_PERF_PROP_OA_FORMAT,
-
-	/**
-	 * Specifying this property implicitly requests periodic OA unit
-	 * sampling and (at least on Haswell) the sampling frequency is derived
-	 * from this exponent as follows:
-	 *
-	 *   80ns * 2^(period_exponent + 1)
-	 *
-	 * This property is available in perf revision 1.
-	 */
-	DRM_I915_PERF_PROP_OA_EXPONENT,
-
-	/**
-	 * Specifying this property is only valid when specify a context to
-	 * filter with DRM_I915_PERF_PROP_CTX_HANDLE. Specifying this property
-	 * will hold preemption of the particular context we want to gather
-	 * performance data about. The execbuf2 submissions must include a
-	 * drm_i915_gem_execbuffer_ext_perf parameter for this to apply.
-	 *
-	 * This property is available in perf revision 3.
-	 */
-	DRM_I915_PERF_PROP_HOLD_PREEMPTION,
-
-	DRM_I915_PERF_PROP_MAX /* non-ABI */
-};
-
-struct drm_i915_perf_open_param {
-	__u32 flags;
-#define I915_PERF_FLAG_FD_CLOEXEC	(1<<0)
-#define I915_PERF_FLAG_FD_NONBLOCK	(1<<1)
-#define I915_PERF_FLAG_DISABLED		(1<<2)
-
-	/** The number of u64 (id, value) pairs */
-	__u32 num_properties;
-
-	/**
-	 * Pointer to array of u64 (id, value) pairs configuring the stream
-	 * to open.
-	 */
-	__u64 properties_ptr;
-};
-
-/**
- * Enable data capture for a stream that was either opened in a disabled state
- * via I915_PERF_FLAG_DISABLED or was later disabled via
- * I915_PERF_IOCTL_DISABLE.
- *
- * It is intended to be cheaper to disable and enable a stream than it may be
- * to close and re-open a stream with the same configuration.
- *
- * It's undefined whether any pending data for the stream will be lost.
- *
- * This ioctl is available in perf revision 1.
- */
-#define I915_PERF_IOCTL_ENABLE	_IO('i', 0x0)
-
-/**
- * Disable data capture for a stream.
- *
- * It is an error to try and read a stream that is disabled.
- *
- * This ioctl is available in perf revision 1.
- */
-#define I915_PERF_IOCTL_DISABLE	_IO('i', 0x1)
-
-/**
- * Change metrics_set captured by a stream.
- *
- * If the stream is bound to a specific context, the configuration change
- * will performed inline with that context such that it takes effect before
- * the next execbuf submission.
- *
- * Returns the previously bound metrics set id, or a negative error code.
- *
- * This ioctl is available in perf revision 2.
- */
-#define I915_PERF_IOCTL_CONFIG	_IO('i', 0x2)
-
-/**
- * Common to all i915 perf records
- */
-struct drm_i915_perf_record_header {
-	__u32 type;
-	__u16 pad;
-	__u16 size;
-};
-
-enum drm_i915_perf_record_type {
-
-	/**
-	 * Samples are the work horse record type whose contents are extensible
-	 * and defined when opening an i915 perf stream based on the given
-	 * properties.
-	 *
-	 * Boolean properties following the naming convention
-	 * DRM_I915_PERF_SAMPLE_xyz_PROP request the inclusion of 'xyz' data in
-	 * every sample.
-	 *
-	 * The order of these sample properties given by userspace has no
-	 * affect on the ordering of data within a sample. The order is
-	 * documented here.
-	 *
-	 * struct {
-	 *     struct drm_i915_perf_record_header header;
-	 *
-	 *     { u32 oa_report[]; } && DRM_I915_PERF_PROP_SAMPLE_OA
-	 * };
-	 */
-	DRM_I915_PERF_RECORD_SAMPLE = 1,
-
-	/*
-	 * Indicates that one or more OA reports were not written by the
-	 * hardware. This can happen for example if an MI_REPORT_PERF_COUNT
-	 * command collides with periodic sampling - which would be more likely
-	 * at higher sampling frequencies.
-	 */
-	DRM_I915_PERF_RECORD_OA_REPORT_LOST = 2,
-
-	/**
-	 * An error occurred that resulted in all pending OA reports being lost.
-	 */
-	DRM_I915_PERF_RECORD_OA_BUFFER_LOST = 3,
-
-	DRM_I915_PERF_RECORD_MAX /* non-ABI */
-};
-
-/**
- * Structure to upload perf dynamic configuration into the kernel.
- */
-struct drm_i915_perf_oa_config {
-	/** String formatted like "%08x-%04x-%04x-%04x-%012x" */
-	char uuid[36];
-
-	__u32 n_mux_regs;
-	__u32 n_boolean_regs;
-	__u32 n_flex_regs;
-
-	/*
-	 * These fields are pointers to tuples of u32 values (register address,
-	 * value). For example the expected length of the buffer pointed by
-	 * mux_regs_ptr is (2 * sizeof(u32) * n_mux_regs).
-	 */
-	__u64 mux_regs_ptr;
-	__u64 boolean_regs_ptr;
-	__u64 flex_regs_ptr;
-};
-
-struct drm_i915_query_item {
-	__u64 query_id;
-#define DRM_I915_QUERY_TOPOLOGY_INFO    1
-#define DRM_I915_QUERY_ENGINE_INFO	2
-#define DRM_I915_QUERY_PERF_CONFIG      3
-/* Must be kept compact -- no holes and well documented */
-
-	/*
-	 * When set to zero by userspace, this is filled with the size of the
-	 * data to be written at the data_ptr pointer. The kernel sets this
-	 * value to a negative value to signal an error on a particular query
-	 * item.
-	 */
-	__s32 length;
-
-	/*
-	 * When query_id == DRM_I915_QUERY_TOPOLOGY_INFO, must be 0.
-	 *
-	 * When query_id == DRM_I915_QUERY_PERF_CONFIG, must be one of the
-	 * following :
-	 *         - DRM_I915_QUERY_PERF_CONFIG_LIST
-	 *         - DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID
-	 *         - DRM_I915_QUERY_PERF_CONFIG_FOR_UUID
-	 */
-	__u32 flags;
-#define DRM_I915_QUERY_PERF_CONFIG_LIST          1
-#define DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID 2
-#define DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_ID   3
-
-	/*
-	 * Data will be written at the location pointed by data_ptr when the
-	 * value of length matches the length of the data to be written by the
-	 * kernel.
-	 */
-	__u64 data_ptr;
-};
-
-struct drm_i915_query {
-	__u32 num_items;
-
-	/*
-	 * Unused for now. Must be cleared to zero.
-	 */
-	__u32 flags;
-
-	/*
-	 * This points to an array of num_items drm_i915_query_item structures.
-	 */
-	__u64 items_ptr;
-};
-
-/*
- * Data written by the kernel with query DRM_I915_QUERY_TOPOLOGY_INFO :
- *
- * data: contains the 3 pieces of information :
- *
- * - the slice mask with one bit per slice telling whether a slice is
- *   available. The availability of slice X can be queried with the following
- *   formula :
- *
- *           (data[X / 8] >> (X % 8)) & 1
- *
- * - the subslice mask for each slice with one bit per subslice telling
- *   whether a subslice is available. Gen12 has dual-subslices, which are
- *   similar to two gen11 subslices. For gen12, this array represents dual-
- *   subslices. The availability of subslice Y in slice X can be queried
- *   with the following formula :
- *
- *           (data[subslice_offset +
- *                 X * subslice_stride +
- *                 Y / 8] >> (Y % 8)) & 1
- *
- * - the EU mask for each subslice in each slice with one bit per EU telling
- *   whether an EU is available. The availability of EU Z in subslice Y in
- *   slice X can be queried with the following formula :
- *
- *           (data[eu_offset +
- *                 (X * max_subslices + Y) * eu_stride +
- *                 Z / 8] >> (Z % 8)) & 1
- */
-struct drm_i915_query_topology_info {
-	/*
-	 * Unused for now. Must be cleared to zero.
-	 */
-	__u16 flags;
-
-	__u16 max_slices;
-	__u16 max_subslices;
-	__u16 max_eus_per_subslice;
-
-	/*
-	 * Offset in data[] at which the subslice masks are stored.
-	 */
-	__u16 subslice_offset;
-
-	/*
-	 * Stride at which each of the subslice masks for each slice are
-	 * stored.
-	 */
-	__u16 subslice_stride;
-
-	/*
-	 * Offset in data[] at which the EU masks are stored.
-	 */
-	__u16 eu_offset;
-
-	/*
-	 * Stride at which each of the EU masks for each subslice are stored.
-	 */
-	__u16 eu_stride;
-
-	__u8 data[];
-};
-
-/**
- * struct drm_i915_engine_info
- *
- * Describes one engine and it's capabilities as known to the driver.
- */
-struct drm_i915_engine_info {
-	/** Engine class and instance. */
-	struct i915_engine_class_instance engine;
-
-	/** Reserved field. */
-	__u32 rsvd0;
-
-	/** Engine flags. */
-	__u64 flags;
-
-	/** Capabilities of this engine. */
-	__u64 capabilities;
-#define I915_VIDEO_CLASS_CAPABILITY_HEVC		(1 << 0)
-#define I915_VIDEO_AND_ENHANCE_CLASS_CAPABILITY_SFC	(1 << 1)
-
-	/** Reserved fields. */
-	__u64 rsvd1[4];
-};
-
-/**
- * struct drm_i915_query_engine_info
- *
- * Engine info query enumerates all engines known to the driver by filling in
- * an array of struct drm_i915_engine_info structures.
- */
-struct drm_i915_query_engine_info {
-	/** Number of struct drm_i915_engine_info structs following. */
-	__u32 num_engines;
-
-	/** MBZ */
-	__u32 rsvd[3];
-
-	/** Marker for drm_i915_engine_info structures. */
-	struct drm_i915_engine_info engines[];
-};
-
-/*
- * Data written by the kernel with query DRM_I915_QUERY_PERF_CONFIG.
- */
-struct drm_i915_query_perf_config {
-	union {
-		/*
-		 * When query_item.flags == DRM_I915_QUERY_PERF_CONFIG_LIST, i915 sets
-		 * this fields to the number of configurations available.
-		 */
-		__u64 n_configs;
-
-		/*
-		 * When query_id == DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_ID,
-		 * i915 will use the value in this field as configuration
-		 * identifier to decide what data to write into config_ptr.
-		 */
-		__u64 config;
-
-		/*
-		 * When query_id == DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID,
-		 * i915 will use the value in this field as configuration
-		 * identifier to decide what data to write into config_ptr.
-		 *
-		 * String formatted like "%08x-%04x-%04x-%04x-%012x"
-		 */
-		char uuid[36];
-	};
-
-	/*
-	 * Unused for now. Must be cleared to zero.
-	 */
-	__u32 flags;
-
-	/*
-	 * When query_item.flags == DRM_I915_QUERY_PERF_CONFIG_LIST, i915 will
-	 * write an array of __u64 of configuration identifiers.
-	 *
-	 * When query_item.flags == DRM_I915_QUERY_PERF_CONFIG_DATA, i915 will
-	 * write a struct drm_i915_perf_oa_config. If the following fields of
-	 * drm_i915_perf_oa_config are set not set to 0, i915 will write into
-	 * the associated pointers the values of submitted when the
-	 * configuration was created :
-	 *
-	 *         - n_mux_regs
-	 *         - n_boolean_regs
-	 *         - n_flex_regs
-	 */
-	__u8 data[];
-};
-
-#if defined(__cplusplus)
-}
-#endif
-
-#endif /* _UAPI_I915_DRM_H_ */
diff --git a/external/virgl_protocol.h b/external/virgl_protocol.h
deleted file mode 100644
index d9884df..0000000
--- a/external/virgl_protocol.h
+++ /dev/null
@@ -1,632 +0,0 @@
-/*
- * Copyright 2014, 2015 Red Hat.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef VIRGL_PROTOCOL_H
-#define VIRGL_PROTOCOL_H
-
-#define VIRGL_QUERY_STATE_NEW 0
-#define VIRGL_QUERY_STATE_DONE 1
-#define VIRGL_QUERY_STATE_WAIT_HOST 2
-
-struct virgl_host_query_state {
-   uint32_t query_state;
-   uint32_t result_size;
-   uint64_t result;
-};
-
-enum virgl_object_type {
-   VIRGL_OBJECT_NULL,
-   VIRGL_OBJECT_BLEND,
-   VIRGL_OBJECT_RASTERIZER,
-   VIRGL_OBJECT_DSA,
-   VIRGL_OBJECT_SHADER,
-   VIRGL_OBJECT_VERTEX_ELEMENTS,
-   VIRGL_OBJECT_SAMPLER_VIEW,
-   VIRGL_OBJECT_SAMPLER_STATE,
-   VIRGL_OBJECT_SURFACE,
-   VIRGL_OBJECT_QUERY,
-   VIRGL_OBJECT_STREAMOUT_TARGET,
-   VIRGL_MAX_OBJECTS,
-};
-
-/* context cmds to be encoded in the command stream */
-enum virgl_context_cmd {
-   VIRGL_CCMD_NOP = 0,
-   VIRGL_CCMD_CREATE_OBJECT = 1,
-   VIRGL_CCMD_BIND_OBJECT,
-   VIRGL_CCMD_DESTROY_OBJECT,
-   VIRGL_CCMD_SET_VIEWPORT_STATE,
-   VIRGL_CCMD_SET_FRAMEBUFFER_STATE,
-   VIRGL_CCMD_SET_VERTEX_BUFFERS,
-   VIRGL_CCMD_CLEAR,
-   VIRGL_CCMD_DRAW_VBO,
-   VIRGL_CCMD_RESOURCE_INLINE_WRITE,
-   VIRGL_CCMD_SET_SAMPLER_VIEWS,
-   VIRGL_CCMD_SET_INDEX_BUFFER,
-   VIRGL_CCMD_SET_CONSTANT_BUFFER,
-   VIRGL_CCMD_SET_STENCIL_REF,
-   VIRGL_CCMD_SET_BLEND_COLOR,
-   VIRGL_CCMD_SET_SCISSOR_STATE,
-   VIRGL_CCMD_BLIT,
-   VIRGL_CCMD_RESOURCE_COPY_REGION,
-   VIRGL_CCMD_BIND_SAMPLER_STATES,
-   VIRGL_CCMD_BEGIN_QUERY,
-   VIRGL_CCMD_END_QUERY,
-   VIRGL_CCMD_GET_QUERY_RESULT,
-   VIRGL_CCMD_SET_POLYGON_STIPPLE,
-   VIRGL_CCMD_SET_CLIP_STATE,
-   VIRGL_CCMD_SET_SAMPLE_MASK,
-   VIRGL_CCMD_SET_STREAMOUT_TARGETS,
-   VIRGL_CCMD_SET_RENDER_CONDITION,
-   VIRGL_CCMD_SET_UNIFORM_BUFFER,
-
-   VIRGL_CCMD_SET_SUB_CTX,
-   VIRGL_CCMD_CREATE_SUB_CTX,
-   VIRGL_CCMD_DESTROY_SUB_CTX,
-   VIRGL_CCMD_BIND_SHADER,
-   VIRGL_CCMD_SET_TESS_STATE,
-   VIRGL_CCMD_SET_MIN_SAMPLES,
-   VIRGL_CCMD_SET_SHADER_BUFFERS,
-   VIRGL_CCMD_SET_SHADER_IMAGES,
-   VIRGL_CCMD_MEMORY_BARRIER,
-   VIRGL_CCMD_LAUNCH_GRID,
-   VIRGL_CCMD_SET_FRAMEBUFFER_STATE_NO_ATTACH,
-   VIRGL_CCMD_TEXTURE_BARRIER,
-   VIRGL_CCMD_SET_ATOMIC_BUFFERS,
-   VIRGL_CCMD_SET_DEBUG_FLAGS,
-   VIRGL_CCMD_GET_QUERY_RESULT_QBO,
-   VIRGL_CCMD_TRANSFER3D,
-   VIRGL_CCMD_END_TRANSFERS,
-   VIRGL_CCMD_COPY_TRANSFER3D,
-   VIRGL_CCMD_SET_TWEAKS,
-   VIRGL_CCMD_CLEAR_TEXTURE,
-   VIRGL_CCMD_PIPE_RESOURCE_CREATE,
-};
-
-/*
- 8-bit cmd headers
- 8-bit object type
- 16-bit length
-*/
-
-#define VIRGL_CMD0(cmd, obj, len) ((cmd) | ((obj) << 8) | ((len) << 16))
-#define VIRGL_CMD0_MAX_DWORDS (((1ULL << 16) - 1) / 4) * 4
-
-/* hw specification */
-#define VIRGL_MAX_COLOR_BUFS 8
-#define VIRGL_MAX_CLIP_PLANES 8
-
-#define VIRGL_OBJ_CREATE_HEADER 0
-#define VIRGL_OBJ_CREATE_HANDLE 1
-
-#define VIRGL_OBJ_BIND_HEADER 0
-#define VIRGL_OBJ_BIND_HANDLE 1
-
-#define VIRGL_OBJ_DESTROY_HANDLE 1
-
-/* some of these defines are a specification - not used in the code */
-/* bit offsets for blend state object */
-#define VIRGL_OBJ_BLEND_SIZE (VIRGL_MAX_COLOR_BUFS + 3)
-#define VIRGL_OBJ_BLEND_HANDLE 1
-#define VIRGL_OBJ_BLEND_S0 2
-#define VIRGL_OBJ_BLEND_S0_INDEPENDENT_BLEND_ENABLE(x) ((x) & 0x1 << 0)
-#define VIRGL_OBJ_BLEND_S0_LOGICOP_ENABLE(x) (((x) & 0x1) << 1)
-#define VIRGL_OBJ_BLEND_S0_DITHER(x) (((x) & 0x1) << 2)
-#define VIRGL_OBJ_BLEND_S0_ALPHA_TO_COVERAGE(x) (((x) & 0x1) << 3)
-#define VIRGL_OBJ_BLEND_S0_ALPHA_TO_ONE(x) (((x) & 0x1) << 4)
-#define VIRGL_OBJ_BLEND_S1 3
-#define VIRGL_OBJ_BLEND_S1_LOGICOP_FUNC(x) (((x) & 0xf) << 0)
-/* repeated once per number of cbufs */
-
-#define VIRGL_OBJ_BLEND_S2(cbuf) (4 + (cbuf))
-#define VIRGL_OBJ_BLEND_S2_RT_BLEND_ENABLE(x) (((x) & 0x1) << 0)
-#define VIRGL_OBJ_BLEND_S2_RT_RGB_FUNC(x) (((x) & 0x7) << 1)
-#define VIRGL_OBJ_BLEND_S2_RT_RGB_SRC_FACTOR(x) (((x) & 0x1f) << 4)
-#define VIRGL_OBJ_BLEND_S2_RT_RGB_DST_FACTOR(x) (((x) & 0x1f) << 9)
-#define VIRGL_OBJ_BLEND_S2_RT_ALPHA_FUNC(x) (((x) & 0x7) << 14)
-#define VIRGL_OBJ_BLEND_S2_RT_ALPHA_SRC_FACTOR(x) (((x) & 0x1f) << 17)
-#define VIRGL_OBJ_BLEND_S2_RT_ALPHA_DST_FACTOR(x) (((x) & 0x1f) << 22)
-#define VIRGL_OBJ_BLEND_S2_RT_COLORMASK(x) (((x) & 0xf) << 27)
-
-/* bit offsets for DSA state */
-#define VIRGL_OBJ_DSA_SIZE 5
-#define VIRGL_OBJ_DSA_HANDLE 1
-#define VIRGL_OBJ_DSA_S0 2
-#define VIRGL_OBJ_DSA_S0_DEPTH_ENABLE(x) (((x) & 0x1) << 0)
-#define VIRGL_OBJ_DSA_S0_DEPTH_WRITEMASK(x) (((x) & 0x1) << 1)
-#define VIRGL_OBJ_DSA_S0_DEPTH_FUNC(x) (((x) & 0x7) << 2)
-#define VIRGL_OBJ_DSA_S0_ALPHA_ENABLED(x) (((x) & 0x1) << 8)
-#define VIRGL_OBJ_DSA_S0_ALPHA_FUNC(x) (((x) & 0x7) << 9)
-#define VIRGL_OBJ_DSA_S1 3
-#define VIRGL_OBJ_DSA_S2 4
-#define VIRGL_OBJ_DSA_S1_STENCIL_ENABLED(x) (((x) & 0x1) << 0)
-#define VIRGL_OBJ_DSA_S1_STENCIL_FUNC(x) (((x) & 0x7) << 1)
-#define VIRGL_OBJ_DSA_S1_STENCIL_FAIL_OP(x) (((x) & 0x7) << 4)
-#define VIRGL_OBJ_DSA_S1_STENCIL_ZPASS_OP(x) (((x) & 0x7) << 7)
-#define VIRGL_OBJ_DSA_S1_STENCIL_ZFAIL_OP(x) (((x) & 0x7) << 10)
-#define VIRGL_OBJ_DSA_S1_STENCIL_VALUEMASK(x) (((x) & 0xff) << 13)
-#define VIRGL_OBJ_DSA_S1_STENCIL_WRITEMASK(x) (((x) & 0xff) << 21)
-#define VIRGL_OBJ_DSA_ALPHA_REF 5
-
-/* offsets for rasterizer state */
-#define VIRGL_OBJ_RS_SIZE 9
-#define VIRGL_OBJ_RS_HANDLE 1
-#define VIRGL_OBJ_RS_S0 2
-#define VIRGL_OBJ_RS_S0_FLATSHADE(x) (((x) & 0x1) << 0)
-#define VIRGL_OBJ_RS_S0_DEPTH_CLIP(x) (((x) & 0x1) << 1)
-#define VIRGL_OBJ_RS_S0_CLIP_HALFZ(x) (((x) & 0x1) << 2)
-#define VIRGL_OBJ_RS_S0_RASTERIZER_DISCARD(x) (((x) & 0x1) << 3)
-#define VIRGL_OBJ_RS_S0_FLATSHADE_FIRST(x) (((x) & 0x1) << 4)
-#define VIRGL_OBJ_RS_S0_LIGHT_TWOSIZE(x) (((x) & 0x1) << 5)
-#define VIRGL_OBJ_RS_S0_SPRITE_COORD_MODE(x) (((x) & 0x1) << 6)
-#define VIRGL_OBJ_RS_S0_POINT_QUAD_RASTERIZATION(x) (((x) & 0x1) << 7)
-#define VIRGL_OBJ_RS_S0_CULL_FACE(x) (((x) & 0x3) << 8)
-#define VIRGL_OBJ_RS_S0_FILL_FRONT(x) (((x) & 0x3) << 10)
-#define VIRGL_OBJ_RS_S0_FILL_BACK(x) (((x) & 0x3) << 12)
-#define VIRGL_OBJ_RS_S0_SCISSOR(x) (((x) & 0x1) << 14)
-#define VIRGL_OBJ_RS_S0_FRONT_CCW(x) (((x) & 0x1) << 15)
-#define VIRGL_OBJ_RS_S0_CLAMP_VERTEX_COLOR(x) (((x) & 0x1) << 16)
-#define VIRGL_OBJ_RS_S0_CLAMP_FRAGMENT_COLOR(x) (((x) & 0x1) << 17)
-#define VIRGL_OBJ_RS_S0_OFFSET_LINE(x) (((x) & 0x1) << 18)
-#define VIRGL_OBJ_RS_S0_OFFSET_POINT(x) (((x) & 0x1) << 19)
-#define VIRGL_OBJ_RS_S0_OFFSET_TRI(x) (((x) & 0x1) << 20)
-#define VIRGL_OBJ_RS_S0_POLY_SMOOTH(x) (((x) & 0x1) << 21)
-#define VIRGL_OBJ_RS_S0_POLY_STIPPLE_ENABLE(x) (((x) & 0x1) << 22)
-#define VIRGL_OBJ_RS_S0_POINT_SMOOTH(x) (((x) & 0x1) << 23)
-#define VIRGL_OBJ_RS_S0_POINT_SIZE_PER_VERTEX(x) (((x) & 0x1) << 24)
-#define VIRGL_OBJ_RS_S0_MULTISAMPLE(x) (((x) & 0x1) << 25)
-#define VIRGL_OBJ_RS_S0_LINE_SMOOTH(x) (((x) & 0x1) << 26)
-#define VIRGL_OBJ_RS_S0_LINE_STIPPLE_ENABLE(x) (((x) & 0x1) << 27)
-#define VIRGL_OBJ_RS_S0_LINE_LAST_PIXEL(x) (((x) & 0x1) << 28)
-#define VIRGL_OBJ_RS_S0_HALF_PIXEL_CENTER(x) (((x) & 0x1) << 29)
-#define VIRGL_OBJ_RS_S0_BOTTOM_EDGE_RULE(x) (((x) & 0x1) << 30)
-#define VIRGL_OBJ_RS_S0_FORCE_PERSAMPLE_INTERP(x) (((x) & 0x1) << 31)
-
-#define VIRGL_OBJ_RS_POINT_SIZE 3
-#define VIRGL_OBJ_RS_SPRITE_COORD_ENABLE 4
-#define VIRGL_OBJ_RS_S3 5
-
-#define VIRGL_OBJ_RS_S3_LINE_STIPPLE_PATTERN(x) (((x) & 0xffff) << 0)
-#define VIRGL_OBJ_RS_S3_LINE_STIPPLE_FACTOR(x) (((x) & 0xff) << 16)
-#define VIRGL_OBJ_RS_S3_CLIP_PLANE_ENABLE(x) (((x) & 0xff) << 24)
-#define VIRGL_OBJ_RS_LINE_WIDTH 6
-#define VIRGL_OBJ_RS_OFFSET_UNITS 7
-#define VIRGL_OBJ_RS_OFFSET_SCALE 8
-#define VIRGL_OBJ_RS_OFFSET_CLAMP 9
-
-#define VIRGL_OBJ_CLEAR_SIZE 8
-#define VIRGL_OBJ_CLEAR_BUFFERS 1
-#define VIRGL_OBJ_CLEAR_COLOR_0 2 /* color is 4 * u32/f32/i32 */
-#define VIRGL_OBJ_CLEAR_COLOR_1 3
-#define VIRGL_OBJ_CLEAR_COLOR_2 4
-#define VIRGL_OBJ_CLEAR_COLOR_3 5
-#define VIRGL_OBJ_CLEAR_DEPTH_0 6 /* depth is a double precision float */
-#define VIRGL_OBJ_CLEAR_DEPTH_1 7
-#define VIRGL_OBJ_CLEAR_STENCIL 8
-
-/* shader object */
-#define VIRGL_OBJ_SHADER_HDR_SIZE(nso) (5 + ((nso) ? (2 * nso) + 4 : 0))
-#define VIRGL_OBJ_SHADER_HANDLE 1
-#define VIRGL_OBJ_SHADER_TYPE 2
-#define VIRGL_OBJ_SHADER_OFFSET 3
-#define VIRGL_OBJ_SHADER_OFFSET_VAL(x) (((x) & 0x7fffffff) << 0)
-/* start contains full length in VAL - also implies continuations */
-/* continuation contains offset in VAL */
-#define VIRGL_OBJ_SHADER_OFFSET_CONT (0x1u << 31)
-#define VIRGL_OBJ_SHADER_NUM_TOKENS 4
-#define VIRGL_OBJ_SHADER_SO_NUM_OUTPUTS 5
-#define VIRGL_OBJ_SHADER_SO_STRIDE(x) (6 + (x))
-#define VIRGL_OBJ_SHADER_SO_OUTPUT0(x) (10 + (x * 2))
-#define VIRGL_OBJ_SHADER_SO_OUTPUT_REGISTER_INDEX(x) (((x) & 0xff) << 0)
-#define VIRGL_OBJ_SHADER_SO_OUTPUT_START_COMPONENT(x) (((x) & 0x3) << 8)
-#define VIRGL_OBJ_SHADER_SO_OUTPUT_NUM_COMPONENTS(x) (((x) & 0x7) << 10)
-#define VIRGL_OBJ_SHADER_SO_OUTPUT_BUFFER(x) (((x) & 0x7) << 13)
-#define VIRGL_OBJ_SHADER_SO_OUTPUT_DST_OFFSET(x) (((x) & 0xffff) << 16)
-#define VIRGL_OBJ_SHADER_SO_OUTPUT0_SO(x) (11 + (x * 2))
-#define VIRGL_OBJ_SHADER_SO_OUTPUT_STREAM(x) (((x) & 0x03) << 0)
-
-/* viewport state */
-#define VIRGL_SET_VIEWPORT_STATE_SIZE(num_viewports) ((6 * num_viewports) + 1)
-#define VIRGL_SET_VIEWPORT_START_SLOT 1
-#define VIRGL_SET_VIEWPORT_STATE_SCALE_0(x) (2 + (x * 6))
-#define VIRGL_SET_VIEWPORT_STATE_SCALE_1(x) (3 + (x * 6))
-#define VIRGL_SET_VIEWPORT_STATE_SCALE_2(x) (4 + (x * 6))
-#define VIRGL_SET_VIEWPORT_STATE_TRANSLATE_0(x) (5 + (x * 6))
-#define VIRGL_SET_VIEWPORT_STATE_TRANSLATE_1(x) (6 + (x * 6))
-#define VIRGL_SET_VIEWPORT_STATE_TRANSLATE_2(x) (7 + (x * 6))
-
-/* framebuffer state */
-#define VIRGL_SET_FRAMEBUFFER_STATE_SIZE(nr_cbufs) (nr_cbufs + 2)
-#define VIRGL_SET_FRAMEBUFFER_STATE_NR_CBUFS 1
-#define VIRGL_SET_FRAMEBUFFER_STATE_NR_ZSURF_HANDLE 2
-#define VIRGL_SET_FRAMEBUFFER_STATE_CBUF_HANDLE(x) ((x) + 3)
-
-/* vertex elements object */
-#define VIRGL_OBJ_VERTEX_ELEMENTS_SIZE(num_elements) (((num_elements) * 4) + 1)
-#define VIRGL_OBJ_VERTEX_ELEMENTS_HANDLE 1
-#define VIRGL_OBJ_VERTEX_ELEMENTS_V0_SRC_OFFSET(x) (((x) * 4) + 2) /* repeated per VE */
-#define VIRGL_OBJ_VERTEX_ELEMENTS_V0_INSTANCE_DIVISOR(x) (((x) * 4) + 3)
-#define VIRGL_OBJ_VERTEX_ELEMENTS_V0_VERTEX_BUFFER_INDEX(x) (((x) * 4) + 4)
-#define VIRGL_OBJ_VERTEX_ELEMENTS_V0_SRC_FORMAT(x) (((x) * 4) + 5)
-
-/* vertex buffers */
-#define VIRGL_SET_VERTEX_BUFFERS_SIZE(num_buffers) ((num_buffers) * 3)
-#define VIRGL_SET_VERTEX_BUFFER_STRIDE(x) (((x) * 3) + 1)
-#define VIRGL_SET_VERTEX_BUFFER_OFFSET(x) (((x) * 3) + 2)
-#define VIRGL_SET_VERTEX_BUFFER_HANDLE(x) (((x) * 3) + 3)
-
-/* index buffer */
-#define VIRGL_SET_INDEX_BUFFER_SIZE(ib) (((ib) ? 2 : 0) + 1)
-#define VIRGL_SET_INDEX_BUFFER_HANDLE 1
-#define VIRGL_SET_INDEX_BUFFER_INDEX_SIZE 2 /* only if sending an IB handle */
-#define VIRGL_SET_INDEX_BUFFER_OFFSET 3     /* only if sending an IB handle */
-
-/* constant buffer */
-#define VIRGL_SET_CONSTANT_BUFFER_SHADER_TYPE 1
-#define VIRGL_SET_CONSTANT_BUFFER_INDEX 2
-#define VIRGL_SET_CONSTANT_BUFFER_DATA_START 3
-
-#define VIRGL_SET_UNIFORM_BUFFER_SIZE 5
-#define VIRGL_SET_UNIFORM_BUFFER_SHADER_TYPE 1
-#define VIRGL_SET_UNIFORM_BUFFER_INDEX 2
-#define VIRGL_SET_UNIFORM_BUFFER_OFFSET 3
-#define VIRGL_SET_UNIFORM_BUFFER_LENGTH 4
-#define VIRGL_SET_UNIFORM_BUFFER_RES_HANDLE 5
-
-/* draw VBO */
-#define VIRGL_DRAW_VBO_SIZE 12
-#define VIRGL_DRAW_VBO_SIZE_TESS 14
-#define VIRGL_DRAW_VBO_SIZE_INDIRECT 20
-#define VIRGL_DRAW_VBO_START 1
-#define VIRGL_DRAW_VBO_COUNT 2
-#define VIRGL_DRAW_VBO_MODE 3
-#define VIRGL_DRAW_VBO_INDEXED 4
-#define VIRGL_DRAW_VBO_INSTANCE_COUNT 5
-#define VIRGL_DRAW_VBO_INDEX_BIAS 6
-#define VIRGL_DRAW_VBO_START_INSTANCE 7
-#define VIRGL_DRAW_VBO_PRIMITIVE_RESTART 8
-#define VIRGL_DRAW_VBO_RESTART_INDEX 9
-#define VIRGL_DRAW_VBO_MIN_INDEX 10
-#define VIRGL_DRAW_VBO_MAX_INDEX 11
-#define VIRGL_DRAW_VBO_COUNT_FROM_SO 12
-/* tess packet */
-#define VIRGL_DRAW_VBO_VERTICES_PER_PATCH 13
-#define VIRGL_DRAW_VBO_DRAWID 14
-/* indirect packet */
-#define VIRGL_DRAW_VBO_INDIRECT_HANDLE 15
-#define VIRGL_DRAW_VBO_INDIRECT_OFFSET 16
-#define VIRGL_DRAW_VBO_INDIRECT_STRIDE 17
-#define VIRGL_DRAW_VBO_INDIRECT_DRAW_COUNT 18
-#define VIRGL_DRAW_VBO_INDIRECT_DRAW_COUNT_OFFSET 19
-#define VIRGL_DRAW_VBO_INDIRECT_DRAW_COUNT_HANDLE 20
-
-/* create surface */
-#define VIRGL_OBJ_SURFACE_SIZE 5
-#define VIRGL_OBJ_SURFACE_HANDLE 1
-#define VIRGL_OBJ_SURFACE_RES_HANDLE 2
-#define VIRGL_OBJ_SURFACE_FORMAT 3
-#define VIRGL_OBJ_SURFACE_BUFFER_FIRST_ELEMENT 4
-#define VIRGL_OBJ_SURFACE_BUFFER_LAST_ELEMENT 5
-#define VIRGL_OBJ_SURFACE_TEXTURE_LEVEL 4
-#define VIRGL_OBJ_SURFACE_TEXTURE_LAYERS 5
-
-/* create streamout target */
-#define VIRGL_OBJ_STREAMOUT_SIZE 4
-#define VIRGL_OBJ_STREAMOUT_HANDLE 1
-#define VIRGL_OBJ_STREAMOUT_RES_HANDLE 2
-#define VIRGL_OBJ_STREAMOUT_BUFFER_OFFSET 3
-#define VIRGL_OBJ_STREAMOUT_BUFFER_SIZE 4
-
-/* sampler state */
-#define VIRGL_OBJ_SAMPLER_STATE_SIZE 9
-#define VIRGL_OBJ_SAMPLER_STATE_HANDLE 1
-#define VIRGL_OBJ_SAMPLER_STATE_S0 2
-#define VIRGL_OBJ_SAMPLE_STATE_S0_WRAP_S(x) (((x) & 0x7) << 0)
-#define VIRGL_OBJ_SAMPLE_STATE_S0_WRAP_T(x) (((x) & 0x7) << 3)
-#define VIRGL_OBJ_SAMPLE_STATE_S0_WRAP_R(x) (((x) & 0x7) << 6)
-#define VIRGL_OBJ_SAMPLE_STATE_S0_MIN_IMG_FILTER(x) (((x) & 0x3) << 9)
-#define VIRGL_OBJ_SAMPLE_STATE_S0_MIN_MIP_FILTER(x) (((x) & 0x3) << 11)
-#define VIRGL_OBJ_SAMPLE_STATE_S0_MAG_IMG_FILTER(x) (((x) & 0x3) << 13)
-#define VIRGL_OBJ_SAMPLE_STATE_S0_COMPARE_MODE(x) (((x) & 0x1) << 15)
-#define VIRGL_OBJ_SAMPLE_STATE_S0_COMPARE_FUNC(x) (((x) & 0x7) << 16)
-#define VIRGL_OBJ_SAMPLE_STATE_S0_SEAMLESS_CUBE_MAP(x) (((x) & 0x1) << 19)
-
-#define VIRGL_OBJ_SAMPLER_STATE_LOD_BIAS 3
-#define VIRGL_OBJ_SAMPLER_STATE_MIN_LOD 4
-#define VIRGL_OBJ_SAMPLER_STATE_MAX_LOD 5
-#define VIRGL_OBJ_SAMPLER_STATE_BORDER_COLOR(x) ((x) + 6) /* 6 - 9 */
-
-
-/* sampler view */
-#define VIRGL_OBJ_SAMPLER_VIEW_SIZE 6
-#define VIRGL_OBJ_SAMPLER_VIEW_HANDLE 1
-#define VIRGL_OBJ_SAMPLER_VIEW_RES_HANDLE 2
-#define VIRGL_OBJ_SAMPLER_VIEW_FORMAT 3
-#define VIRGL_OBJ_SAMPLER_VIEW_BUFFER_FIRST_ELEMENT 4
-#define VIRGL_OBJ_SAMPLER_VIEW_BUFFER_LAST_ELEMENT 5
-#define VIRGL_OBJ_SAMPLER_VIEW_TEXTURE_LAYER 4
-#define VIRGL_OBJ_SAMPLER_VIEW_TEXTURE_LEVEL 5
-#define VIRGL_OBJ_SAMPLER_VIEW_SWIZZLE 6
-#define VIRGL_OBJ_SAMPLER_VIEW_SWIZZLE_R(x) (((x) & 0x7) << 0)
-#define VIRGL_OBJ_SAMPLER_VIEW_SWIZZLE_G(x) (((x) & 0x7) << 3)
-#define VIRGL_OBJ_SAMPLER_VIEW_SWIZZLE_B(x) (((x) & 0x7) << 6)
-#define VIRGL_OBJ_SAMPLER_VIEW_SWIZZLE_A(x) (((x) & 0x7) << 9)
-
-/* set sampler views */
-#define VIRGL_SET_SAMPLER_VIEWS_SIZE(num_views) ((num_views) + 2)
-#define VIRGL_SET_SAMPLER_VIEWS_SHADER_TYPE 1
-#define VIRGL_SET_SAMPLER_VIEWS_START_SLOT 2
-#define VIRGL_SET_SAMPLER_VIEWS_V0_HANDLE 3
-
-/* bind sampler states */
-#define VIRGL_BIND_SAMPLER_STATES(num_states) ((num_states) + 2)
-#define VIRGL_BIND_SAMPLER_STATES_SHADER_TYPE 1
-#define VIRGL_BIND_SAMPLER_STATES_START_SLOT 2
-#define VIRGL_BIND_SAMPLER_STATES_S0_HANDLE 3
-
-/* set stencil reference */
-#define VIRGL_SET_STENCIL_REF_SIZE 1
-#define VIRGL_SET_STENCIL_REF 1
-#define VIRGL_STENCIL_REF_VAL(f, s) ((f & 0xff) | (((s & 0xff) << 8)))
-
-/* set blend color */
-#define VIRGL_SET_BLEND_COLOR_SIZE 4
-#define VIRGL_SET_BLEND_COLOR(x) ((x) + 1)
-
-/* set scissor state */
-#define VIRGL_SET_SCISSOR_STATE_SIZE(x) (1 + 2 * x)
-#define VIRGL_SET_SCISSOR_START_SLOT 1
-#define VIRGL_SET_SCISSOR_MINX_MINY(x) (2 + (x * 2))
-#define VIRGL_SET_SCISSOR_MAXX_MAXY(x) (3 + (x * 2))
-
-/* resource copy region */
-#define VIRGL_CMD_RESOURCE_COPY_REGION_SIZE 13
-#define VIRGL_CMD_RCR_DST_RES_HANDLE 1
-#define VIRGL_CMD_RCR_DST_LEVEL 2
-#define VIRGL_CMD_RCR_DST_X 3
-#define VIRGL_CMD_RCR_DST_Y 4
-#define VIRGL_CMD_RCR_DST_Z 5
-#define VIRGL_CMD_RCR_SRC_RES_HANDLE 6
-#define VIRGL_CMD_RCR_SRC_LEVEL 7
-#define VIRGL_CMD_RCR_SRC_X 8
-#define VIRGL_CMD_RCR_SRC_Y 9
-#define VIRGL_CMD_RCR_SRC_Z 10
-#define VIRGL_CMD_RCR_SRC_W 11
-#define VIRGL_CMD_RCR_SRC_H 12
-#define VIRGL_CMD_RCR_SRC_D 13
-
-/* blit */
-#define VIRGL_CMD_BLIT_SIZE 21
-#define VIRGL_CMD_BLIT_S0 1
-#define VIRGL_CMD_BLIT_S0_MASK(x) (((x) & 0xff) << 0)
-#define VIRGL_CMD_BLIT_S0_FILTER(x) (((x) & 0x3) << 8)
-#define VIRGL_CMD_BLIT_S0_SCISSOR_ENABLE(x) (((x) & 0x1) << 10)
-#define VIRGL_CMD_BLIT_S0_RENDER_CONDITION_ENABLE(x) (((x) & 0x1) << 11)
-#define VIRGL_CMD_BLIT_S0_ALPHA_BLEND(x) (((x) & 0x1) << 12)
-#define VIRGL_CMD_BLIT_SCISSOR_MINX_MINY 2
-#define VIRGL_CMD_BLIT_SCISSOR_MAXX_MAXY 3
-#define VIRGL_CMD_BLIT_DST_RES_HANDLE 4
-#define VIRGL_CMD_BLIT_DST_LEVEL 5
-#define VIRGL_CMD_BLIT_DST_FORMAT 6
-#define VIRGL_CMD_BLIT_DST_X 7
-#define VIRGL_CMD_BLIT_DST_Y 8
-#define VIRGL_CMD_BLIT_DST_Z 9
-#define VIRGL_CMD_BLIT_DST_W 10
-#define VIRGL_CMD_BLIT_DST_H 11
-#define VIRGL_CMD_BLIT_DST_D 12
-#define VIRGL_CMD_BLIT_SRC_RES_HANDLE 13
-#define VIRGL_CMD_BLIT_SRC_LEVEL 14
-#define VIRGL_CMD_BLIT_SRC_FORMAT 15
-#define VIRGL_CMD_BLIT_SRC_X 16
-#define VIRGL_CMD_BLIT_SRC_Y 17
-#define VIRGL_CMD_BLIT_SRC_Z 18
-#define VIRGL_CMD_BLIT_SRC_W 19
-#define VIRGL_CMD_BLIT_SRC_H 20
-#define VIRGL_CMD_BLIT_SRC_D 21
-
-/* query object */
-#define VIRGL_OBJ_QUERY_SIZE 4
-#define VIRGL_OBJ_QUERY_HANDLE 1
-#define VIRGL_OBJ_QUERY_TYPE_INDEX 2
-#define VIRGL_OBJ_QUERY_TYPE(x) (x & 0xffff)
-#define VIRGL_OBJ_QUERY_INDEX(x) ((x & 0xffff) << 16)
-#define VIRGL_OBJ_QUERY_OFFSET 3
-#define VIRGL_OBJ_QUERY_RES_HANDLE 4
-
-#define VIRGL_QUERY_BEGIN_HANDLE 1
-
-#define VIRGL_QUERY_END_HANDLE 1
-
-#define VIRGL_QUERY_RESULT_SIZE 2
-#define VIRGL_QUERY_RESULT_HANDLE 1
-#define VIRGL_QUERY_RESULT_WAIT 2
-
-/* render condition */
-#define VIRGL_RENDER_CONDITION_SIZE 3
-#define VIRGL_RENDER_CONDITION_HANDLE 1
-#define VIRGL_RENDER_CONDITION_CONDITION 2
-#define VIRGL_RENDER_CONDITION_MODE 3
-
-/* resource inline write */
-#define VIRGL_RESOURCE_IW_RES_HANDLE 1
-#define VIRGL_RESOURCE_IW_LEVEL 2
-#define VIRGL_RESOURCE_IW_USAGE 3
-#define VIRGL_RESOURCE_IW_STRIDE 4
-#define VIRGL_RESOURCE_IW_LAYER_STRIDE 5
-#define VIRGL_RESOURCE_IW_X 6
-#define VIRGL_RESOURCE_IW_Y 7
-#define VIRGL_RESOURCE_IW_Z 8
-#define VIRGL_RESOURCE_IW_W 9
-#define VIRGL_RESOURCE_IW_H 10
-#define VIRGL_RESOURCE_IW_D 11
-#define VIRGL_RESOURCE_IW_DATA_START 12
-
-/* set streamout targets */
-#define VIRGL_SET_STREAMOUT_TARGETS_APPEND_BITMASK 1
-#define VIRGL_SET_STREAMOUT_TARGETS_H0 2
-
-/* set sample mask */
-#define VIRGL_SET_SAMPLE_MASK_SIZE 1
-#define VIRGL_SET_SAMPLE_MASK_MASK 1
-
-/* set clip state */
-#define VIRGL_SET_CLIP_STATE_SIZE 32
-#define VIRGL_SET_CLIP_STATE_C0 1
-
-/* polygon stipple */
-#define VIRGL_POLYGON_STIPPLE_SIZE 32
-#define VIRGL_POLYGON_STIPPLE_P0 1
-
-#define VIRGL_BIND_SHADER_SIZE 2
-#define VIRGL_BIND_SHADER_HANDLE 1
-#define VIRGL_BIND_SHADER_TYPE 2
-
-/* tess state */
-#define VIRGL_TESS_STATE_SIZE 6
-
-/* set min samples */
-#define VIRGL_SET_MIN_SAMPLES_SIZE 1
-#define VIRGL_SET_MIN_SAMPLES_MASK 1
-
-/* set shader buffers */
-#define VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE 3
-#define VIRGL_SET_SHADER_BUFFER_SIZE(x) (VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE * (x)) + 2
-#define VIRGL_SET_SHADER_BUFFER_SHADER_TYPE 1
-#define VIRGL_SET_SHADER_BUFFER_START_SLOT 2
-#define VIRGL_SET_SHADER_BUFFER_OFFSET(x) ((x) * VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE + 3)
-#define VIRGL_SET_SHADER_BUFFER_LENGTH(x) ((x) * VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE + 4)
-#define VIRGL_SET_SHADER_BUFFER_RES_HANDLE(x) ((x) * VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE + 5)
-
-/* set shader images */
-#define VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE 5
-#define VIRGL_SET_SHADER_IMAGE_SIZE(x) (VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE * (x)) + 2
-#define VIRGL_SET_SHADER_IMAGE_SHADER_TYPE 1
-#define VIRGL_SET_SHADER_IMAGE_START_SLOT 2
-#define VIRGL_SET_SHADER_IMAGE_FORMAT(x) ((x) * VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE + 3)
-#define VIRGL_SET_SHADER_IMAGE_ACCESS(x) ((x) * VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE + 4)
-#define VIRGL_SET_SHADER_IMAGE_LAYER_OFFSET(x) ((x) * VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE + 5)
-#define VIRGL_SET_SHADER_IMAGE_LEVEL_SIZE(x) ((x) * VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE + 6)
-#define VIRGL_SET_SHADER_IMAGE_RES_HANDLE(x) ((x) * VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE + 7)
-
-/* memory barrier */
-#define VIRGL_MEMORY_BARRIER_SIZE 1
-#define VIRGL_MEMORY_BARRIER_FLAGS 1
-
-/* launch grid */
-#define VIRGL_LAUNCH_GRID_SIZE 8
-#define VIRGL_LAUNCH_BLOCK_X 1
-#define VIRGL_LAUNCH_BLOCK_Y 2
-#define VIRGL_LAUNCH_BLOCK_Z 3
-#define VIRGL_LAUNCH_GRID_X 4
-#define VIRGL_LAUNCH_GRID_Y 5
-#define VIRGL_LAUNCH_GRID_Z 6
-#define VIRGL_LAUNCH_INDIRECT_HANDLE 7
-#define VIRGL_LAUNCH_INDIRECT_OFFSET 8
-
-/* framebuffer state no attachment */
-#define VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_SIZE 2
-#define VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_WIDTH_HEIGHT 1
-#define VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_WIDTH(x) (x & 0xffff)
-#define VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_HEIGHT(x) ((x >> 16) & 0xffff)
-#define VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_LAYERS_SAMPLES 2
-#define VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_LAYERS(x) (x & 0xffff)
-#define VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_SAMPLES(x) ((x >> 16) & 0xff)
-
-/* texture barrier */
-#define VIRGL_TEXTURE_BARRIER_SIZE 1
-#define VIRGL_TEXTURE_BARRIER_FLAGS 1
-
-/* hw atomics */
-#define VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE 3
-#define VIRGL_SET_ATOMIC_BUFFER_SIZE(x) (VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE * (x)) + 1
-#define VIRGL_SET_ATOMIC_BUFFER_START_SLOT 1
-#define VIRGL_SET_ATOMIC_BUFFER_OFFSET(x) ((x) * VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE + 2)
-#define VIRGL_SET_ATOMIC_BUFFER_LENGTH(x) ((x) * VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE + 3)
-#define VIRGL_SET_ATOMIC_BUFFER_RES_HANDLE(x) ((x) * VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE + 4)
-
-/* qbo */
-#define VIRGL_QUERY_RESULT_QBO_SIZE 6
-#define VIRGL_QUERY_RESULT_QBO_HANDLE 1
-#define VIRGL_QUERY_RESULT_QBO_QBO_HANDLE 2
-#define VIRGL_QUERY_RESULT_QBO_WAIT 3
-#define VIRGL_QUERY_RESULT_QBO_RESULT_TYPE 4
-#define VIRGL_QUERY_RESULT_QBO_OFFSET 5
-#define VIRGL_QUERY_RESULT_QBO_INDEX 6
-
-#define VIRGL_TRANSFER_TO_HOST   1
-#define VIRGL_TRANSFER_FROM_HOST 2
-
-/* Transfer */
-#define VIRGL_TRANSFER3D_SIZE 13
-/* The first 11 dwords are the same as VIRGL_RESOURCE_IW_*  */
-#define VIRGL_TRANSFER3D_DATA_OFFSET 12
-#define VIRGL_TRANSFER3D_DIRECTION 13
-
-/* Copy transfer */
-#define VIRGL_COPY_TRANSFER3D_SIZE 14
-/* The first 11 dwords are the same as VIRGL_RESOURCE_IW_*  */
-#define VIRGL_COPY_TRANSFER3D_SRC_RES_HANDLE 12
-#define VIRGL_COPY_TRANSFER3D_SRC_RES_OFFSET 13
-#define VIRGL_COPY_TRANSFER3D_SYNCHRONIZED 14
-
-/* set tweak flags */
-#define VIRGL_SET_TWEAKS_SIZE 2
-#define VIRGL_SET_TWEAKS_ID 1
-#define VIRGL_SET_TWEAKS_VALUE 2
-
-/* virgl create */
-#define VIRGL_PIPE_RES_CREATE_SIZE 11
-#define VIRGL_PIPE_RES_CREATE_TARGET 1
-#define VIRGL_PIPE_RES_CREATE_FORMAT 2
-#define VIRGL_PIPE_RES_CREATE_BIND 3
-#define VIRGL_PIPE_RES_CREATE_WIDTH 4
-#define VIRGL_PIPE_RES_CREATE_HEIGHT 5
-#define VIRGL_PIPE_RES_CREATE_DEPTH 6
-#define VIRGL_PIPE_RES_CREATE_ARRAY_SIZE 7
-#define VIRGL_PIPE_RES_CREATE_LAST_LEVEL 8
-#define VIRGL_PIPE_RES_CREATE_NR_SAMPLES 9
-#define VIRGL_PIPE_RES_CREATE_FLAGS 10
-#define VIRGL_PIPE_RES_CREATE_BLOB_ID 11
-
-enum vrend_tweak_type {
-   virgl_tweak_gles_brga_emulate,
-   virgl_tweak_gles_brga_apply_dest_swizzle,
-   virgl_tweak_gles_tf3_samples_passes_multiplier,
-   virgl_tweak_undefined
-};
-
-/* Clear texture */
-#define VIRGL_CLEAR_TEXTURE_SIZE 12
-#define VIRGL_TEXTURE_HANDLE 1
-#define VIRGL_TEXTURE_LEVEL 2
-#define VIRGL_TEXTURE_SRC_X 3
-#define VIRGL_TEXTURE_SRC_Y 4
-#define VIRGL_TEXTURE_SRC_Z 5
-#define VIRGL_TEXTURE_SRC_W 6
-#define VIRGL_TEXTURE_SRC_H 7
-#define VIRGL_TEXTURE_SRC_D 8
-#define VIRGL_TEXTURE_ARRAY_A 9
-#define VIRGL_TEXTURE_ARRAY_B 10
-#define VIRGL_TEXTURE_ARRAY_C 11
-#define VIRGL_TEXTURE_ARRAY_D 12
-
-#endif
diff --git a/external/virtgpu_cross_domain_protocol.h b/external/virtgpu_cross_domain_protocol.h
deleted file mode 100644
index eaeebd3..0000000
--- a/external/virtgpu_cross_domain_protocol.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2021 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef VIRTGPU_CROSS_DOMAIN_PROTOCOL_H
-#define VIRTGPU_CROSS_DOMAIN_PROTOCOL_H
-
-#include <stdint.h>
-
-// Cross-domain commands (only a maximum of 255 supported)
-#define CROSS_DOMAIN_CMD_INIT 1
-#define CROSS_DOMAIN_CMD_GET_IMAGE_REQUIREMENTS 2
-
-// Channel types (must match rutabaga channel types)
-#define CROSS_DOMAIN_CHANNEL_TYPE_WAYLAND 0x0001
-#define CROSS_DOMAIN_CHANNEL_TYPE_CAMERA 0x0002
-
-struct CrossDomainCapabilities {
-	uint32_t version;
-	uint32_t supported_channels;
-	uint32_t supports_dmabuf;
-	uint32_t supports_external_gpu_memory;
-};
-
-struct CrossDomainImageRequirements {
-	uint32_t strides[4];
-	uint32_t offsets[4];
-	uint64_t modifier;
-	uint64_t size;
-	uint64_t blob_id;
-	uint32_t map_info;
-	uint32_t pad;
-	int32_t memory_idx;
-	int32_t physical_device_idx;
-};
-
-struct CrossDomainHeader {
-	uint8_t cmd;
-	uint8_t fence_ctx_idx;
-	uint16_t cmd_size;
-	uint32_t pad;
-};
-
-struct CrossDomainInit {
-	struct CrossDomainHeader hdr;
-	uint32_t ring_id;
-	uint32_t channel_type;
-};
-
-struct CrossDomainGetImageRequirements {
-	struct CrossDomainHeader hdr;
-	uint32_t width;
-	uint32_t height;
-	uint32_t drm_format;
-	uint32_t flags;
-};
-
-#endif
diff --git a/exynos.c b/exynos.c
index 5862643..6a80107 100644
--- a/exynos.c
+++ b/exynos.c
@@ -64,8 +64,9 @@
 	int ret;
 	for (plane = 0; plane < bo->meta.num_planes; plane++) {
 		size_t size = bo->meta.sizes[plane];
-		struct drm_exynos_gem_create gem_create = { 0 };
+		struct drm_exynos_gem_create gem_create;
 
+		memset(&gem_create, 0, sizeof(gem_create));
 		gem_create.size = size;
 		gem_create.flags = EXYNOS_BO_NONCONTIG;
 
@@ -83,8 +84,8 @@
 
 cleanup_planes:
 	for (; plane != 0; plane--) {
-		struct drm_gem_close gem_close = { 0 };
-
+		struct drm_gem_close gem_close;
+		memset(&gem_close, 0, sizeof(gem_close));
 		gem_close.handle = bo->handles[plane - 1].u32;
 		int gem_close_ret = drmIoctl(bo->drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
 		if (gem_close_ret) {
diff --git a/gbm.c b/gbm.c
index ecbfb88..ab5b3f7 100644
--- a/gbm.c
+++ b/gbm.c
@@ -140,9 +140,9 @@
 		return NULL;
 
 	/*
-	 * HACK: This is for HAL_PIXEL_FORMAT_YV12 buffers allocated by arcvm. None of
-	 * our platforms can display YV12, so we can treat as a SW buffer. Remove once
-	 * this can be intelligently resolved in the guest. Also see compute_virgl_bind_flags.
+	 * HACK: This is for HAL_PIXEL_FORMAT_YV12 buffers allocated by arcvm.
+	 * None of our platforms can display YV12, so we can treat as a SW buffer.
+	 * Remove once this can be intelligently resolved in the guest.
 	 */
 	if (format == GBM_FORMAT_YVU420 && (usage & GBM_BO_USE_LINEAR))
 		format = DRM_FORMAT_YVU420_ANDROID;
@@ -194,12 +194,13 @@
 				    uint32_t usage)
 {
 	struct gbm_bo *bo;
-	struct drv_import_fd_data drv_data = { 0 };
+	struct drv_import_fd_data drv_data;
 	struct gbm_import_fd_data *fd_data = buffer;
 	struct gbm_import_fd_modifier_data *fd_modifier_data = buffer;
 	uint32_t gbm_format;
 	size_t num_planes, i, num_fds;
 
+	memset(&drv_data, 0, sizeof(drv_data));
 	drv_data.use_flags = gbm_convert_usage(usage);
 	switch (type) {
 	case GBM_BO_IMPORT_FD:
@@ -209,8 +210,9 @@
 		drv_data.format = fd_data->format;
 		drv_data.fds[0] = fd_data->fd;
 		drv_data.strides[0] = fd_data->stride;
-		drv_data.format_modifier = DRM_FORMAT_MOD_INVALID;
 
+		for (i = 0; i < GBM_MAX_PLANES; ++i)
+			drv_data.format_modifiers[i] = DRM_FORMAT_MOD_INVALID;
 		break;
 	case GBM_BO_IMPORT_FD_MODIFIER:
 		gbm_format = fd_modifier_data->format;
@@ -225,7 +227,6 @@
 		if (!num_fds || num_fds > num_planes)
 			return NULL;
 
-		drv_data.format_modifier = fd_modifier_data->modifier;
 		for (i = 0; i < num_planes; i++) {
 			if (num_fds != num_planes)
 				drv_data.fds[i] = fd_modifier_data->fds[0];
@@ -233,6 +234,7 @@
 				drv_data.fds[i] = fd_modifier_data->fds[i];
 			drv_data.offsets[i] = fd_modifier_data->offsets[i];
 			drv_data.strides[i] = fd_modifier_data->strides[i];
+			drv_data.format_modifiers[i] = fd_modifier_data->modifier;
 		}
 
 		for (i = num_planes; i < GBM_MAX_PLANES; i++)
@@ -261,12 +263,6 @@
 	return bo;
 }
 
-PUBLIC void *gbm_bo_map(struct gbm_bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height,
-			uint32_t transfer_flags, uint32_t *stride, void **map_data)
-{
-	return gbm_bo_map2(bo, x, y, width, height, transfer_flags, stride, map_data, 0);
-}
-
 PUBLIC void gbm_bo_unmap(struct gbm_bo *bo, void *map_data)
 {
 	assert(bo);
@@ -300,7 +296,7 @@
 
 PUBLIC uint64_t gbm_bo_get_modifier(struct gbm_bo *bo)
 {
-	return drv_bo_get_format_modifier(bo->bo);
+	return drv_bo_get_plane_format_modifier(bo->bo, 0);
 }
 
 PUBLIC struct gbm_device *gbm_bo_get_device(struct gbm_bo *bo)
@@ -328,11 +324,6 @@
 	return (union gbm_bo_handle)drv_bo_get_plane_handle(bo->bo, (size_t)plane).u64;
 }
 
-PUBLIC int gbm_bo_get_fd_for_plane(struct gbm_bo *bo, int plane)
-{
-	return drv_bo_get_plane_fd(bo->bo, plane);
-}
-
 PUBLIC uint32_t gbm_bo_get_offset(struct gbm_bo *bo, size_t plane)
 {
 	return drv_bo_get_plane_offset(bo->bo, (size_t)plane);
@@ -402,6 +393,12 @@
 	return drv_bo_get_plane_fd(bo->bo, plane);
 }
 
+PUBLIC void *gbm_bo_map(struct gbm_bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height,
+			uint32_t transfer_flags, uint32_t *stride, void **map_data, size_t plane)
+{
+	return gbm_bo_map2(bo, x, y, width, height, transfer_flags, stride, map_data, plane);
+}
+
 PUBLIC void *gbm_bo_map2(struct gbm_bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height,
 			 uint32_t transfer_flags, uint32_t *stride, void **map_data, int plane)
 {
diff --git a/gbm.h b/gbm.h
index 9acfaa2..2492728 100644
--- a/gbm.h
+++ b/gbm.h
@@ -72,7 +72,7 @@
 /** Format of the allocated buffer */
 enum gbm_bo_format {
    /** RGB with 8 bits per channel in a 32 bit value */
-   GBM_BO_FORMAT_XRGB8888,
+   GBM_BO_FORMAT_XRGB8888, 
    /** ARGB with 8 bits per channel in a 32 bit value */
    GBM_BO_FORMAT_ARGB8888
 };
@@ -179,8 +179,6 @@
 #define GBM_FORMAT_NV16		__gbm_fourcc_code('N', 'V', '1', '6') /* 2x1 subsampled Cr:Cb plane */
 #define GBM_FORMAT_NV61		__gbm_fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */
 
-#define GBM_FORMAT_P010		__gbm_fourcc_code('P', '0', '1', '0') /* 2x2 subsampled Cr:Cb plane */
-
 /*
  * 3 plane YCbCr
  * index 0: Y plane, [7:0] Y
@@ -282,14 +280,6 @@
     * which would otherwise access the underlying buffer will fail.
     */
    GBM_TEST_ALLOC = (1 << 15),
-
-   /**
-    * The buffer will be used for front buffer rendering.  On some
-    * platforms this may (for example) disable framebuffer compression
-    * to avoid problems with compression flags data being out of sync
-    * with pixel data.
-    */
-   GBM_BO_USE_FRONT_RENDERING = (1 << 16),
 };
 
 int
@@ -383,11 +373,6 @@
    GBM_BO_TRANSFER_READ_WRITE = (GBM_BO_TRANSFER_READ | GBM_BO_TRANSFER_WRITE),
 };
 
-void *
-gbm_bo_map(struct gbm_bo *bo,
-           uint32_t x, uint32_t y, uint32_t width, uint32_t height,
-           uint32_t flags, uint32_t *stride, void **map_data);
-
 void
 gbm_bo_unmap(struct gbm_bo *bo, void *map_data);
 
@@ -431,9 +416,6 @@
 gbm_bo_get_handle_for_plane(struct gbm_bo *bo, size_t plane);
 
 int
-gbm_bo_get_fd_for_plane(struct gbm_bo *bo, int plane);
-
-int
 gbm_bo_write(struct gbm_bo *bo, const void *buf, size_t count);
 
 void
@@ -489,6 +471,10 @@
 gbm_bo_get_plane_fd(struct gbm_bo *bo, size_t plane);
 
 void *
+gbm_bo_map(struct gbm_bo *bo,
+           uint32_t x, uint32_t y, uint32_t width, uint32_t height,
+           uint32_t flags, uint32_t *stride, void **map_data, size_t plane);
+void *
 gbm_bo_map2(struct gbm_bo *bo,
 	   uint32_t x, uint32_t y, uint32_t width, uint32_t height,
 	   uint32_t flags, uint32_t *stride, void **map_data, int plane);
diff --git a/gbm_helpers.c b/gbm_helpers.c
index 17dcf1f..0626a6d 100644
--- a/gbm_helpers.c
+++ b/gbm_helpers.c
@@ -44,8 +44,6 @@
 		use_flags |= BO_USE_HW_VIDEO_DECODER;
 	if (usage & GBM_BO_USE_HW_VIDEO_ENCODER)
 		use_flags |= BO_USE_HW_VIDEO_ENCODER;
-	if (usage & GBM_BO_USE_FRONT_RENDERING)
-		use_flags |= BO_USE_FRONT_RENDERING;
 
 	return use_flags;
 }
diff --git a/helpers.c b/helpers.c
index a182347..17b1765 100644
--- a/helpers.c
+++ b/helpers.c
@@ -189,8 +189,7 @@
 	if (!planes)
 		return 0;
 
-	if (drv->backend->num_planes_from_modifier && modifier != DRM_FORMAT_MOD_INVALID &&
-	    modifier != DRM_FORMAT_MOD_LINEAR)
+	if (drv->backend->num_planes_from_modifier && modifier != DRM_FORMAT_MOD_INVALID)
 		return drv->backend->num_planes_from_modifier(drv, format, modifier);
 
 	return planes;
@@ -313,7 +312,7 @@
 	int ret;
 	size_t plane;
 	uint32_t aligned_width, aligned_height;
-	struct drm_mode_create_dumb create_dumb = { 0 };
+	struct drm_mode_create_dumb create_dumb;
 
 	aligned_width = width;
 	aligned_height = height;
@@ -339,7 +338,6 @@
 	case DRM_FORMAT_YVU420:
 	case DRM_FORMAT_NV12:
 	case DRM_FORMAT_NV21:
-	case DRM_FORMAT_P010:
 		/* Adjust the height to include room for chroma planes */
 		aligned_height = 3 * DIV_ROUND_UP(height, 2);
 		break;
@@ -347,6 +345,7 @@
 		break;
 	}
 
+	memset(&create_dumb, 0, sizeof(create_dumb));
 	if (quirks & BO_QUIRK_DUMB32BPP) {
 		aligned_width =
 		    DIV_ROUND_UP(aligned_width * layout_from_format(format)->bytes_per_pixel[0], 4);
@@ -381,10 +380,12 @@
 
 int drv_dumb_bo_destroy(struct bo *bo)
 {
+	struct drm_mode_destroy_dumb destroy_dumb;
 	int ret;
-	struct drm_mode_destroy_dumb destroy_dumb = { 0 };
 
+	memset(&destroy_dumb, 0, sizeof(destroy_dumb));
 	destroy_dumb.handle = bo->handles[0].u32;
+
 	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
 	if (ret) {
 		drv_log("DRM_IOCTL_MODE_DESTROY_DUMB failed (handle=%x)\n", bo->handles[0].u32);
@@ -450,7 +451,6 @@
 
 		bo->handles[plane].u32 = prime_handle.handle;
 	}
-	bo->meta.tiling = data->tiling;
 
 	return 0;
 }
@@ -640,28 +640,3 @@
 
 	return false;
 }
-
-/*
- * Map internal fourcc codes back to standard fourcc codes.
- */
-uint32_t drv_get_standard_fourcc(uint32_t fourcc_internal)
-{
-	return (fourcc_internal == DRM_FORMAT_YVU420_ANDROID) ? DRM_FORMAT_YVU420 : fourcc_internal;
-}
-
-uint32_t drv_resolve_format_helper(struct driver *drv, uint32_t format, uint64_t use_flags)
-{
-	switch (format) {
-	case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
-		/* Common camera implementation defined format. */
-		if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE))
-			return DRM_FORMAT_NV12;
-		/* A common hack: See b/28671744 */
-		return DRM_FORMAT_XBGR8888;
-	case DRM_FORMAT_FLEX_YCbCr_420_888:
-		/* Common flexible video format. */
-		return DRM_FORMAT_NV12;
-	default:
-		return format;
-	}
-}
diff --git a/helpers.h b/helpers.h
index d906dcf..19d0fd7 100644
--- a/helpers.h
+++ b/helpers.h
@@ -7,19 +7,11 @@
 #ifndef HELPERS_H
 #define HELPERS_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include <stdbool.h>
 
 #include "drv.h"
 #include "helpers_array.h"
 
-#ifndef PAGE_SIZE
-#define PAGE_SIZE 0x1000
-#endif
-
 uint32_t drv_height_from_format(uint32_t format, uint32_t height, size_t plane);
 uint32_t drv_vertical_subsampling_from_format(uint32_t format, size_t plane);
 uint32_t drv_size_from_format(uint32_t format, uint32_t stride, uint32_t height, size_t plane);
@@ -50,11 +42,4 @@
 uint64_t drv_pick_modifier(const uint64_t *modifiers, uint32_t count,
 			   const uint64_t *modifier_order, uint32_t order_count);
 bool drv_has_modifier(const uint64_t *list, uint32_t count, uint64_t modifier);
-uint32_t drv_get_standard_fourcc(uint32_t fourcc_internal);
-uint32_t drv_resolve_format_helper(struct driver *drv, uint32_t format, uint64_t use_flags);
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/i915.c b/i915.c
index 9de38b2..92fd5b1 100644
--- a/i915.c
+++ b/i915.c
@@ -8,6 +8,7 @@
 
 #include <assert.h>
 #include <errno.h>
+#include <i915_drm.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <string.h>
@@ -16,7 +17,6 @@
 #include <xf86drm.h>
 
 #include "drv_priv.h"
-#include "external/i915_drm.h"
 #include "helpers.h"
 #include "util.h"
 
@@ -34,71 +34,21 @@
 static const uint32_t texture_only_formats[] = { DRM_FORMAT_R8, DRM_FORMAT_NV12, DRM_FORMAT_P010,
 						 DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID };
 
-static const uint64_t gen_modifier_order[] = { I915_FORMAT_MOD_Y_TILED_CCS, I915_FORMAT_MOD_Y_TILED,
-					       I915_FORMAT_MOD_X_TILED, DRM_FORMAT_MOD_LINEAR };
-
-static const uint64_t gen11_modifier_order[] = { I915_FORMAT_MOD_Y_TILED, I915_FORMAT_MOD_X_TILED,
-						 DRM_FORMAT_MOD_LINEAR };
-
-struct modifier_support_t {
-	const uint64_t *order;
-	uint32_t count;
-};
-
 struct i915_device {
 	uint32_t gen;
 	int32_t has_llc;
-	int32_t has_hw_protection;
-	struct modifier_support_t modifier;
-	int device_id;
-	bool is_adlp;
 };
 
-static void i915_info_from_device_id(struct i915_device *i915)
+static uint32_t i915_get_gen(int device_id)
 {
 	const uint16_t gen3_ids[] = { 0x2582, 0x2592, 0x2772, 0x27A2, 0x27AE,
 				      0x29C2, 0x29B2, 0x29D2, 0xA001, 0xA011 };
-	const uint16_t gen11_ids[] = { 0x4E71, 0x4E61, 0x4E51, 0x4E55, 0x4E57 };
-	const uint16_t gen12_ids[] = { 0x9A40, 0x9A49, 0x9A59, 0x9A60, 0x9A68, 0x9A70,
-				       0x9A78, 0x9AC0, 0x9AC9, 0x9AD9, 0x9AF8 };
-	const uint16_t adlp_ids[] = { 0x46A0, 0x46A1, 0x46A2, 0x46A3, 0x46A6,
-				      0x46A8, 0x46AA, 0x462A, 0x4626, 0x4628,
-				      0x46B0, 0x46B1, 0x46B2, 0x46B3, 0x46C0,
-				      0x46C1, 0x46C2, 0x46C3 };
 	unsigned i;
-	i915->gen = 4;
-	i915->is_adlp = false;
-
 	for (i = 0; i < ARRAY_SIZE(gen3_ids); i++)
-		if (gen3_ids[i] == i915->device_id)
-			i915->gen = 3;
+		if (gen3_ids[i] == device_id)
+			return 3;
 
-	/* Gen 11 */
-	for (i = 0; i < ARRAY_SIZE(gen11_ids); i++)
-		if (gen11_ids[i] == i915->device_id)
-			i915->gen = 11;
-
-	/* Gen 12 */
-	for (i = 0; i < ARRAY_SIZE(gen12_ids); i++)
-		if (gen12_ids[i] == i915->device_id)
-			i915->gen = 12;
-
-	for (i = 0; i < ARRAY_SIZE(adlp_ids); i++)
-		if (adlp_ids[i] == i915->device_id) {
-			i915->is_adlp = true;
-			i915->gen = 12;
-		}
-}
-
-static void i915_get_modifier_order(struct i915_device *i915)
-{
-	if (i915->gen == 11) {
-		i915->modifier.order = gen11_modifier_order;
-		i915->modifier.count = ARRAY_SIZE(gen11_modifier_order);
-	} else {
-		i915->modifier.order = gen_modifier_order;
-		i915->modifier.count = ARRAY_SIZE(gen_modifier_order);
-	}
+	return 4;
 }
 
 static uint64_t unset_flags(uint64_t current_flags, uint64_t mask)
@@ -109,88 +59,80 @@
 
 static int i915_add_combinations(struct driver *drv)
 {
-	struct i915_device *i915 = drv->priv;
+	struct format_metadata metadata;
+	uint64_t render, scanout_and_render, texture_only;
 
-	const uint64_t scanout_and_render = BO_USE_RENDER_MASK | BO_USE_SCANOUT;
-	const uint64_t render = BO_USE_RENDER_MASK;
-	const uint64_t texture_only = BO_USE_TEXTURE_MASK;
-	// HW protected buffers also need to be scanned out.
-	const uint64_t hw_protected =
-	    i915->has_hw_protection ? (BO_USE_PROTECTED | BO_USE_SCANOUT) : 0;
+	scanout_and_render = BO_USE_RENDER_MASK | BO_USE_SCANOUT;
+	render = BO_USE_RENDER_MASK;
+	texture_only = BO_USE_TEXTURE_MASK;
+	uint64_t linear_mask = BO_USE_RENDERSCRIPT | BO_USE_LINEAR | BO_USE_PROTECTED |
+			       BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN;
 
-	const uint64_t linear_mask = BO_USE_RENDERSCRIPT | BO_USE_LINEAR | BO_USE_SW_READ_OFTEN |
-				     BO_USE_SW_WRITE_OFTEN | BO_USE_SW_READ_RARELY |
-				     BO_USE_SW_WRITE_RARELY;
-
-	struct format_metadata metadata_linear = { .tiling = I915_TILING_NONE,
-						   .priority = 1,
-						   .modifier = DRM_FORMAT_MOD_LINEAR };
+	metadata.tiling = I915_TILING_NONE;
+	metadata.priority = 1;
+	metadata.modifier = DRM_FORMAT_MOD_LINEAR;
 
 	drv_add_combinations(drv, scanout_render_formats, ARRAY_SIZE(scanout_render_formats),
-			     &metadata_linear, scanout_and_render);
+			     &metadata, scanout_and_render);
 
-	drv_add_combinations(drv, render_formats, ARRAY_SIZE(render_formats), &metadata_linear,
-			     render);
+	drv_add_combinations(drv, render_formats, ARRAY_SIZE(render_formats), &metadata, render);
 
-	drv_add_combinations(drv, texture_only_formats, ARRAY_SIZE(texture_only_formats),
-			     &metadata_linear, texture_only);
+	drv_add_combinations(drv, texture_only_formats, ARRAY_SIZE(texture_only_formats), &metadata,
+			     texture_only);
 
 	drv_modify_linear_combinations(drv);
-
-	/* NV12 format for camera, display, decoding and encoding. */
+	/*
+	 * Chrome uses DMA-buf mmap to write to YV12 buffers, which are then accessed by the
+	 * Video Encoder Accelerator (VEA). It could also support NV12 potentially in the future.
+	 */
+	drv_modify_combination(drv, DRM_FORMAT_YVU420, &metadata, BO_USE_HW_VIDEO_ENCODER);
 	/* IPU3 camera ISP supports only NV12 output. */
-	drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata_linear,
-			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_SCANOUT |
-				   BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER |
-				   hw_protected);
+	drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata,
+			       BO_USE_HW_VIDEO_ENCODER | BO_USE_HW_VIDEO_DECODER |
+				   BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_SCANOUT);
 
 	/* Android CTS tests require this. */
-	drv_add_combination(drv, DRM_FORMAT_BGR888, &metadata_linear, BO_USE_SW_MASK);
+	drv_add_combination(drv, DRM_FORMAT_BGR888, &metadata, BO_USE_SW_MASK);
 
 	/*
 	 * R8 format is used for Android's HAL_PIXEL_FORMAT_BLOB and is used for JPEG snapshots
-	 * from camera and input/output from hardware decoder/encoder.
+	 * from camera.
 	 */
-	drv_modify_combination(drv, DRM_FORMAT_R8, &metadata_linear,
-			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER |
-				   BO_USE_HW_VIDEO_ENCODER);
+	drv_modify_combination(drv, DRM_FORMAT_R8, &metadata,
+			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
 
-	const uint64_t render_not_linear = unset_flags(render, linear_mask);
-	const uint64_t scanout_and_render_not_linear = render_not_linear | BO_USE_SCANOUT;
+	render = unset_flags(render, linear_mask);
+	scanout_and_render = unset_flags(scanout_and_render, linear_mask);
 
-	struct format_metadata metadata_x_tiled = { .tiling = I915_TILING_X,
-						    .priority = 2,
-						    .modifier = I915_FORMAT_MOD_X_TILED };
+	metadata.tiling = I915_TILING_X;
+	metadata.priority = 2;
+	metadata.modifier = I915_FORMAT_MOD_X_TILED;
 
-	drv_add_combinations(drv, render_formats, ARRAY_SIZE(render_formats), &metadata_x_tiled,
-			     render_not_linear);
+	drv_add_combinations(drv, render_formats, ARRAY_SIZE(render_formats), &metadata, render);
 	drv_add_combinations(drv, scanout_render_formats, ARRAY_SIZE(scanout_render_formats),
-			     &metadata_x_tiled, scanout_and_render_not_linear);
+			     &metadata, scanout_and_render);
 
-	struct format_metadata metadata_y_tiled = { .tiling = I915_TILING_Y,
-						    .priority = 3,
-						    .modifier = I915_FORMAT_MOD_Y_TILED };
+	metadata.tiling = I915_TILING_Y;
+	metadata.priority = 3;
+	metadata.modifier = I915_FORMAT_MOD_Y_TILED;
 
+	scanout_and_render =
+	    unset_flags(scanout_and_render, BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY);
 /* Support y-tiled NV12 and P010 for libva */
 #ifdef I915_SCANOUT_Y_TILED
-	const uint64_t nv12_usage =
-	    BO_USE_TEXTURE | BO_USE_HW_VIDEO_DECODER | BO_USE_SCANOUT | hw_protected;
-	const uint64_t p010_usage = BO_USE_TEXTURE | BO_USE_HW_VIDEO_DECODER | hw_protected |
-				    (i915->gen >= 11 ? BO_USE_SCANOUT : 0);
+	drv_add_combination(drv, DRM_FORMAT_NV12, &metadata,
+			    BO_USE_TEXTURE | BO_USE_HW_VIDEO_DECODER | BO_USE_SCANOUT);
 #else
-	const uint64_t nv12_usage = BO_USE_TEXTURE | BO_USE_HW_VIDEO_DECODER;
-	const uint64_t p010_usage = nv12_usage;
+	drv_add_combination(drv, DRM_FORMAT_NV12, &metadata,
+			    BO_USE_TEXTURE | BO_USE_HW_VIDEO_DECODER);
 #endif
-	drv_add_combination(drv, DRM_FORMAT_NV12, &metadata_y_tiled, nv12_usage);
-	drv_add_combination(drv, DRM_FORMAT_P010, &metadata_y_tiled, p010_usage);
+	scanout_and_render = unset_flags(scanout_and_render, BO_USE_SCANOUT);
+	drv_add_combination(drv, DRM_FORMAT_P010, &metadata,
+			    BO_USE_TEXTURE | BO_USE_HW_VIDEO_DECODER);
 
-	drv_add_combinations(drv, render_formats, ARRAY_SIZE(render_formats), &metadata_y_tiled,
-			     render_not_linear);
-
-	// Y-tiled scanout isn't available on old platforms so we add
-	// |scanout_render_formats| without that USE flag.
+	drv_add_combinations(drv, render_formats, ARRAY_SIZE(render_formats), &metadata, render);
 	drv_add_combinations(drv, scanout_render_formats, ARRAY_SIZE(scanout_render_formats),
-			     &metadata_y_tiled, render_not_linear);
+			     &metadata, scanout_and_render);
 	return 0;
 }
 
@@ -211,15 +153,7 @@
 		 * horizontal alignment so that row start on a cache line (64
 		 * bytes).
 		 */
-#ifdef LINEAR_ALIGN_256
-		/*
-		 * If we want to import these buffers to amdgpu they need to
-		 * their match LINEAR_ALIGNED requirement of 256 byte alignement.
-		 */
-		horizontal_alignment = 256;
-#else
 		horizontal_alignment = 64;
-#endif
 		vertical_alignment = 4;
 		break;
 
@@ -249,10 +183,6 @@
 		*stride = horizontal_alignment;
 	}
 
-	/* stride must be power-of-two aligned for ADL-P tiled buffers*/
-	if (i915->is_adlp && (*stride > 1) && (tiling != I915_TILING_NONE))
-		*stride = 1 << (32 - __builtin_clz(*stride -1));
-
 	if (i915->gen <= 3 && *stride > 8192)
 		return -EINVAL;
 
@@ -274,25 +204,25 @@
 static int i915_init(struct driver *drv)
 {
 	int ret;
+	int device_id;
 	struct i915_device *i915;
-	drm_i915_getparam_t get_param = { 0 };
+	drm_i915_getparam_t get_param;
 
 	i915 = calloc(1, sizeof(*i915));
 	if (!i915)
 		return -ENOMEM;
 
+	memset(&get_param, 0, sizeof(get_param));
 	get_param.param = I915_PARAM_CHIPSET_ID;
-	get_param.value = &(i915->device_id);
+	get_param.value = &device_id;
 	ret = drmIoctl(drv->fd, DRM_IOCTL_I915_GETPARAM, &get_param);
 	if (ret) {
 		drv_log("Failed to get I915_PARAM_CHIPSET_ID\n");
 		free(i915);
 		return -EINVAL;
 	}
-	/* must call before i915->gen is used anywhere else */
-	i915_info_from_device_id(i915);
 
-	i915_get_modifier_order(i915);
+	i915->gen = i915_get_gen(device_id);
 
 	memset(&get_param, 0, sizeof(get_param));
 	get_param.param = I915_PARAM_HAS_LLC;
@@ -304,27 +234,9 @@
 		return -EINVAL;
 	}
 
-	if (i915->gen >= 12)
-		i915->has_hw_protection = 1;
-
 	drv->priv = i915;
-	return i915_add_combinations(drv);
-}
 
-/*
- * Returns true if the height of a buffer of the given format should be aligned
- * to the largest coded unit (LCU) assuming that it will be used for video. This
- * is based on gmmlib's GmmIsYUVFormatLCUAligned().
- */
-static bool i915_format_needs_LCU_alignment(uint32_t format, size_t plane, const struct i915_device* i915)
-{
-	switch (format) {
-	case DRM_FORMAT_NV12:
-	case DRM_FORMAT_P010:
-	case DRM_FORMAT_P016:
-		return (i915->gen == 11 || i915->gen == 12) && plane == 1;
-	}
-	return false;
+	return i915_add_combinations(drv);
 }
 
 static int i915_bo_from_format(struct bo *bo, uint32_t width, uint32_t height, uint32_t format)
@@ -332,11 +244,9 @@
 	uint32_t offset;
 	size_t plane;
 	int ret, pagesize;
-	struct i915_device *i915 = bo->drv->priv;
 
 	offset = 0;
 	pagesize = getpagesize();
-
 	for (plane = 0; plane < drv_num_planes_from_format(format); plane++) {
 		uint32_t stride = drv_stride_from_format(format, width, plane);
 		uint32_t plane_height = drv_height_from_format(format, height, plane);
@@ -348,15 +258,6 @@
 		if (ret)
 			return ret;
 
-		if (i915_format_needs_LCU_alignment(format, plane, i915)) {
-			/*
-			 * Align the height of the V plane for certain formats to the
-			 * largest coded unit (assuming that this BO may be used for video)
-			 * to be consistent with gmmlib.
-			 */
-			plane_height = ALIGN(plane_height, 64);
-		}
-
 		bo->meta.strides[plane] = stride;
 		bo->meta.sizes[plane] = stride * plane_height;
 		bo->meta.offsets[plane] = offset;
@@ -371,13 +272,16 @@
 static int i915_bo_compute_metadata(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
 				    uint64_t use_flags, const uint64_t *modifiers, uint32_t count)
 {
+	static const uint64_t modifier_order[] = {
+		I915_FORMAT_MOD_Y_TILED,
+		I915_FORMAT_MOD_X_TILED,
+		DRM_FORMAT_MOD_LINEAR,
+	};
 	uint64_t modifier;
-	struct i915_device *i915 = bo->drv->priv;
-	bool huge_bo = (i915->gen < 11) && (width > 4096);
 
 	if (modifiers) {
 		modifier =
-		    drv_pick_modifier(modifiers, count, i915->modifier.order, i915->modifier.count);
+		    drv_pick_modifier(modifiers, count, modifier_order, ARRAY_SIZE(modifier_order));
 	} else {
 		struct combination *combo = drv_get_combination(bo->drv, format, use_flags);
 		if (!combo)
@@ -385,39 +289,6 @@
 		modifier = combo->metadata.modifier;
 	}
 
-	/*
-	 * i915 only supports linear/x-tiled above 4096 wide on Gen9/Gen10 GPU.
-	 * VAAPI decode in NV12 Y tiled format so skip modifier change for NV12/P010 huge bo.
-	 */
-	if (huge_bo && format != DRM_FORMAT_NV12 && format != DRM_FORMAT_P010 &&
-	    modifier != I915_FORMAT_MOD_X_TILED && modifier != DRM_FORMAT_MOD_LINEAR) {
-		uint32_t i;
-		for (i = 0; modifiers && i < count; i++) {
-			if (modifiers[i] == I915_FORMAT_MOD_X_TILED)
-				break;
-		}
-		if (i == count)
-			modifier = DRM_FORMAT_MOD_LINEAR;
-		else
-			modifier = I915_FORMAT_MOD_X_TILED;
-	}
-
-	/*
-	 * Skip I915_FORMAT_MOD_Y_TILED_CCS modifier if compression is disabled
-	 * Pick y tiled modifier if it has been passed in, otherwise use linear
-	 */
-	if (!bo->drv->compression && modifier == I915_FORMAT_MOD_Y_TILED_CCS) {
-		uint32_t i;
-		for (i = 0; modifiers && i < count; i++) {
-			if (modifiers[i] == I915_FORMAT_MOD_Y_TILED)
-				break;
-		}
-		if (i == count)
-			modifier = DRM_FORMAT_MOD_LINEAR;
-		else
-			modifier = I915_FORMAT_MOD_Y_TILED;
-	}
-
 	switch (modifier) {
 	case DRM_FORMAT_MOD_LINEAR:
 		bo->meta.tiling = I915_TILING_NONE;
@@ -431,7 +302,7 @@
 		break;
 	}
 
-	bo->meta.format_modifier = modifier;
+	bo->meta.format_modifiers[0] = modifier;
 
 	if (format == DRM_FORMAT_YVU420_ANDROID) {
 		/*
@@ -495,56 +366,30 @@
 {
 	int ret;
 	size_t plane;
-	uint32_t gem_handle;
-	struct drm_i915_gem_set_tiling gem_set_tiling = { 0 };
-	struct i915_device *i915 = bo->drv->priv;
+	struct drm_i915_gem_create gem_create;
+	struct drm_i915_gem_set_tiling gem_set_tiling;
 
-	if (i915->has_hw_protection && (bo->meta.use_flags & BO_USE_PROTECTED)) {
-		struct drm_i915_gem_object_param protected_param = {
-			.param = I915_OBJECT_PARAM | I915_PARAM_PROTECTED_CONTENT,
-			.data = 1,
-		};
+	memset(&gem_create, 0, sizeof(gem_create));
+	gem_create.size = bo->meta.total_size;
 
-		struct drm_i915_gem_create_ext_setparam setparam_protected = {
-			.base = { .name = I915_GEM_CREATE_EXT_SETPARAM },
-			.param = protected_param,
-		};
-
-		struct drm_i915_gem_create_ext create_ext = {
-			.size = bo->meta.total_size,
-			.extensions = (uintptr_t)&setparam_protected,
-		};
-
-		ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_CREATE_EXT, &create_ext);
-		if (ret) {
-			drv_log("DRM_IOCTL_I915_GEM_CREATE_EXT failed (size=%llu)\n",
-				create_ext.size);
-			return -errno;
-		}
-
-		gem_handle = create_ext.handle;
-	} else {
-		struct drm_i915_gem_create gem_create = { 0 };
-		gem_create.size = bo->meta.total_size;
-		ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create);
-		if (ret) {
-			drv_log("DRM_IOCTL_I915_GEM_CREATE failed (size=%llu)\n", gem_create.size);
-			return -errno;
-		}
-
-		gem_handle = gem_create.handle;
+	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create);
+	if (ret) {
+		drv_log("DRM_IOCTL_I915_GEM_CREATE failed (size=%llu)\n", gem_create.size);
+		return -errno;
 	}
 
 	for (plane = 0; plane < bo->meta.num_planes; plane++)
-		bo->handles[plane].u32 = gem_handle;
+		bo->handles[plane].u32 = gem_create.handle;
 
+	memset(&gem_set_tiling, 0, sizeof(gem_set_tiling));
 	gem_set_tiling.handle = bo->handles[0].u32;
 	gem_set_tiling.tiling_mode = bo->meta.tiling;
 	gem_set_tiling.stride = bo->meta.strides[0];
 
 	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_SET_TILING, &gem_set_tiling);
 	if (ret) {
-		struct drm_gem_close gem_close = { 0 };
+		struct drm_gem_close gem_close;
+		memset(&gem_close, 0, sizeof(gem_close));
 		gem_close.handle = bo->handles[0].u32;
 		drmIoctl(bo->drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
 
@@ -564,13 +409,14 @@
 static int i915_bo_import(struct bo *bo, struct drv_import_fd_data *data)
 {
 	int ret;
-	struct drm_i915_gem_get_tiling gem_get_tiling = { 0 };
+	struct drm_i915_gem_get_tiling gem_get_tiling;
 
 	ret = drv_prime_bo_import(bo, data);
 	if (ret)
 		return ret;
 
 	/* TODO(gsingh): export modifiers and get rid of backdoor tiling. */
+	memset(&gem_get_tiling, 0, sizeof(gem_get_tiling));
 	gem_get_tiling.handle = bo->handles[0].u32;
 
 	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_GET_TILING, &gem_get_tiling);
@@ -587,13 +433,15 @@
 static void *i915_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
 {
 	int ret;
-	void *addr = MAP_FAILED;
+	void *addr;
 
-	if (bo->meta.format_modifier == I915_FORMAT_MOD_Y_TILED_CCS)
+	if (bo->meta.format_modifiers[0] == I915_FORMAT_MOD_Y_TILED_CCS)
 		return MAP_FAILED;
 
 	if (bo->meta.tiling == I915_TILING_NONE) {
-		struct drm_i915_gem_mmap gem_map = { 0 };
+		struct drm_i915_gem_mmap gem_map;
+		memset(&gem_map, 0, sizeof(gem_map));
+
 		/* TODO(b/118799155): We don't seem to have a good way to
 		 * detect the use cases for which WC mapping is really needed.
 		 * The current heuristic seems overly coarse and may be slowing
@@ -612,21 +460,18 @@
 		gem_map.size = bo->meta.total_size;
 
 		ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_MMAP, &gem_map);
-		/* DRM_IOCTL_I915_GEM_MMAP mmaps the underlying shm
-		 * file and returns a user space address directly, ie,
-		 * doesn't go through mmap. If we try that on a
-		 * dma-buf that doesn't have a shm file, i915.ko
-		 * returns ENXIO.  Fall through to
-		 * DRM_IOCTL_I915_GEM_MMAP_GTT in that case, which
-		 * will mmap on the drm fd instead. */
-		if (ret == 0)
-			addr = (void *)(uintptr_t)gem_map.addr_ptr;
-	}
+		if (ret) {
+			drv_log("DRM_IOCTL_I915_GEM_MMAP failed\n");
+			return MAP_FAILED;
+		}
 
-	if (addr == MAP_FAILED) {
-		struct drm_i915_gem_mmap_gtt gem_map = { 0 };
+		addr = (void *)(uintptr_t)gem_map.addr_ptr;
+	} else {
+		struct drm_i915_gem_mmap_gtt gem_map;
+		memset(&gem_map, 0, sizeof(gem_map));
 
 		gem_map.handle = bo->handles[0].u32;
+
 		ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &gem_map);
 		if (ret) {
 			drv_log("DRM_IOCTL_I915_GEM_MMAP_GTT failed\n");
@@ -649,8 +494,9 @@
 static int i915_bo_invalidate(struct bo *bo, struct mapping *mapping)
 {
 	int ret;
-	struct drm_i915_gem_set_domain set_domain = { 0 };
+	struct drm_i915_gem_set_domain set_domain;
 
+	memset(&set_domain, 0, sizeof(set_domain));
 	set_domain.handle = bo->handles[0].u32;
 	if (bo->meta.tiling == I915_TILING_NONE) {
 		set_domain.read_domains = I915_GEM_DOMAIN_CPU;
@@ -680,6 +526,31 @@
 	return 0;
 }
 
+static uint32_t i915_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags)
+{
+	switch (format) {
+	case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
+		/* KBL camera subsystem requires NV12. */
+		if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE))
+			return DRM_FORMAT_NV12;
+		/*HACK: See b/28671744 */
+		return DRM_FORMAT_XBGR8888;
+	case DRM_FORMAT_FLEX_YCbCr_420_888:
+		/*
+		 * KBL camera subsystem requires NV12. Our other use cases
+		 * don't care:
+		 * - Hardware video supports NV12,
+		 * - USB Camera HALv3 supports NV12,
+		 * - USB Camera HALv1 doesn't use this format.
+		 * Moreover, NV12 is preferred for video, due to overlay
+		 * support on SKL+.
+		 */
+		return DRM_FORMAT_NV12;
+	default:
+		return format;
+	}
+}
+
 const struct backend backend_i915 = {
 	.name = "i915",
 	.init = i915_init,
@@ -692,7 +563,7 @@
 	.bo_unmap = drv_bo_munmap,
 	.bo_invalidate = i915_bo_invalidate,
 	.bo_flush = i915_bo_flush,
-	.resolve_format = drv_resolve_format_helper,
+	.resolve_format = i915_resolve_format,
 };
 
 #endif
diff --git a/marvell.c b/marvell.c
new file mode 100644
index 0000000..c0b600b
--- /dev/null
+++ b/marvell.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifdef DRV_MARVELL
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 };
+
+static int marvell_init(struct driver *drv)
+{
+	drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+			     &LINEAR_METADATA, BO_USE_RENDER_MASK);
+
+	return drv_add_linear_combinations(drv, render_target_formats,
+					   ARRAY_SIZE(render_target_formats));
+}
+
+const struct backend backend_marvell = {
+	.name = "marvell",
+	.init = marvell_init,
+	.bo_create = drv_dumb_bo_create,
+	.bo_destroy = drv_dumb_bo_destroy,
+	.bo_import = drv_prime_bo_import,
+	.bo_map = drv_dumb_bo_map,
+	.bo_unmap = drv_bo_munmap,
+};
+
+#endif
diff --git a/mediatek.c b/mediatek.c
index de492e2..cdfc9ab 100644
--- a/mediatek.c
+++ b/mediatek.c
@@ -54,7 +54,14 @@
 	drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats),
 			     &LINEAR_METADATA, BO_USE_TEXTURE_MASK);
 
-	drv_add_combination(drv, DRM_FORMAT_R8, &LINEAR_METADATA, BO_USE_SW_MASK | BO_USE_LINEAR);
+	drv_add_combination(drv, DRM_FORMAT_R8, &LINEAR_METADATA,
+			    BO_USE_SW_MASK | BO_USE_LINEAR | BO_USE_PROTECTED);
+	/*
+	 * Chrome uses DMA-buf mmap to write to YV12 buffers, which are then accessed by the
+	 * Video Encoder Accelerator (VEA). It could also support NV12 potentially in the future.
+	 */
+	drv_modify_combination(drv, DRM_FORMAT_YVU420, &LINEAR_METADATA, BO_USE_HW_VIDEO_ENCODER);
+	drv_modify_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA, BO_USE_HW_VIDEO_ENCODER);
 
 	/* Android CTS tests require this. */
 	drv_add_combination(drv, DRM_FORMAT_BGR888, &LINEAR_METADATA, BO_USE_SW_MASK);
@@ -65,32 +72,20 @@
 	metadata.modifier = DRM_FORMAT_MOD_LINEAR;
 	drv_modify_combination(drv, DRM_FORMAT_YVU420, &metadata, BO_USE_HW_VIDEO_DECODER);
 	drv_modify_combination(drv, DRM_FORMAT_YVU420_ANDROID, &metadata, BO_USE_HW_VIDEO_DECODER);
-#if defined(MTK_MT8183) || defined(MTK_MT8192) || defined(MTK_MT8195)
-	// TODO(hiroh): Switch to use NV12 for video decoder on MT8173 as well.
 	drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata, BO_USE_HW_VIDEO_DECODER);
-#endif
-
-	/*
-	 * R8 format is used for Android's HAL_PIXEL_FORMAT_BLOB for input/output from
-	 * hardware decoder/encoder.
-	 */
-	drv_modify_combination(drv, DRM_FORMAT_R8, &metadata,
-			       BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER |
-				   BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
-
-	/* NV12 format for encoding and display. */
-	drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata,
-			       BO_USE_SCANOUT | BO_USE_HW_VIDEO_ENCODER | BO_USE_CAMERA_READ |
-				   BO_USE_CAMERA_WRITE);
 
 #ifdef MTK_MT8183
 	/* Only for MT8183 Camera subsystem */
+	drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata,
+			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
 	drv_modify_combination(drv, DRM_FORMAT_NV21, &metadata,
 			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
 	drv_modify_combination(drv, DRM_FORMAT_YUYV, &metadata,
 			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
 	drv_modify_combination(drv, DRM_FORMAT_YVU420, &metadata,
 			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
+	drv_modify_combination(drv, DRM_FORMAT_R8, &metadata,
+			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
 	/* Private formats for private reprocessing in camera */
 	drv_add_combination(drv, DRM_FORMAT_MTISP_SXYZW10, &metadata,
 			    BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_SW_MASK);
@@ -106,7 +101,7 @@
 	int ret;
 	size_t plane;
 	uint32_t stride;
-	struct drm_mtk_gem_create gem_create = { 0 };
+	struct drm_mtk_gem_create gem_create;
 
 	if (!drv_has_modifier(modifiers, count, DRM_FORMAT_MOD_LINEAR)) {
 		errno = EINVAL;
@@ -145,6 +140,7 @@
 		drv_bo_from_format(bo, stride, height, format);
 	}
 
+	memset(&gem_create, 0, sizeof(gem_create));
 	gem_create.size = bo->meta.total_size;
 
 	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MTK_GEM_CREATE, &gem_create);
@@ -170,9 +166,10 @@
 static void *mediatek_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
 {
 	int ret, prime_fd;
-	struct drm_mtk_gem_map_off gem_map = { 0 };
+	struct drm_mtk_gem_map_off gem_map;
 	struct mediatek_private_map_data *priv;
 
+	memset(&gem_map, 0, sizeof(gem_map));
 	gem_map.handle = bo->handles[0].u32;
 
 	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MTK_GEM_MAP_OFFSET, &gem_map);
@@ -268,23 +265,21 @@
 		 * reprocessing and hence given the private format for MTK. */
 		if (use_flags & BO_USE_CAMERA_READ)
 			return DRM_FORMAT_MTISP_SXYZW10;
-#endif
-		if (use_flags & BO_USE_CAMERA_WRITE)
+		/* For non-reprocessing uses, only MT8183 Camera subsystem
+		 * requires NV12. */
+		else if (use_flags & BO_USE_CAMERA_WRITE)
 			return DRM_FORMAT_NV12;
-
+#endif
 		/*HACK: See b/28671744 */
 		return DRM_FORMAT_XBGR8888;
 	case DRM_FORMAT_FLEX_YCbCr_420_888:
-#if defined(MTK_MT8183) || defined(MTK_MT8192) || defined(MTK_MT8195)
-		// TODO(hiroh): Switch to use NV12 for video decoder on MT8173 as well.
-		if (use_flags & (BO_USE_HW_VIDEO_DECODER)) {
+#ifdef MTK_MT8183
+		/* MT8183 camera and decoder subsystems require NV12. */
+		if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE |
+				 BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER)) {
 			return DRM_FORMAT_NV12;
 		}
 #endif
-		if (use_flags &
-		    (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_ENCODER)) {
-			return DRM_FORMAT_NV12;
-		}
 		return DRM_FORMAT_YVU420;
 	default:
 		return format;
diff --git a/meson.c b/meson.c
new file mode 100644
index 0000000..f82c57a
--- /dev/null
+++ b/meson.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2018 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifdef DRV_MESON
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+static const uint32_t scanout_render_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888,
+						   DRM_FORMAT_ABGR8888, DRM_FORMAT_XBGR8888,
+						   DRM_FORMAT_BGR888, DRM_FORMAT_BGR565};
+
+static int meson_init(struct driver *drv)
+{
+	drv_add_combinations(drv, scanout_render_formats, ARRAY_SIZE(scanout_render_formats),
+			     &LINEAR_METADATA, BO_USE_RENDER_MASK | BO_USE_SCANOUT);
+
+	return drv_modify_linear_combinations(drv);
+}
+
+const struct backend backend_meson = {
+	.name = "meson",
+	.init = meson_init,
+	.bo_create = drv_dumb_bo_create,
+	.bo_destroy = drv_dumb_bo_destroy,
+	.bo_import = drv_prime_bo_import,
+	.bo_map = drv_dumb_bo_map,
+	.bo_unmap = drv_bo_munmap,
+};
+
+#endif
diff --git a/minigbm_helpers.c b/minigbm_helpers.c
deleted file mode 100644
index 137e5a1..0000000
--- a/minigbm_helpers.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * Copyright 2020 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include <amdgpu_drm.h>
-#include <ctype.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <radeon_drm.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <xf86drm.h>
-#include <xf86drmMode.h>
-
-#include "minigbm_helpers.h"
-#include "util.h"
-
-/* These are set in stone. from drm_pciids.h */
-static unsigned int radeon_igp_ids[] = {
-	0x1304, 0x1305, 0x1306, 0x1307, 0x1309, 0x130A, 0x130B, 0x130C, 0x130D, 0x130E, 0x130F,
-	0x1310, 0x1311, 0x1312, 0x1313, 0x1315, 0x1316, 0x1317, 0x1318, 0x131B, 0x131C, 0x131D,
-	0x4136, 0x4137, 0x4237, 0x4336, 0x4337, 0x4437, 0x5834, 0x5835, 0x5954, 0x5955, 0x5974,
-	0x5975, 0x5a41, 0x5a42, 0x5a61, 0x5a62, 0x7834, 0x7835, 0x791e, 0x791f, 0x793f, 0x7941,
-	0x7942, 0x796c, 0x796d, 0x796e, 0x796f, 0x9610, 0x9611, 0x9612, 0x9613, 0x9614, 0x9615,
-	0x9616, 0x9640, 0x9641, 0x9642, 0x9643, 0x9644, 0x9645, 0x9647, 0x9648, 0x9649, 0x964a,
-	0x964b, 0x964c, 0x964e, 0x964f, 0x9710, 0x9711, 0x9712, 0x9713, 0x9714, 0x9715, 0x9802,
-	0x9803, 0x9804, 0x9805, 0x9806, 0x9807, 0x9808, 0x9809, 0x980A, 0x9830, 0x9831, 0x9832,
-	0x9833, 0x9834, 0x9835, 0x9836, 0x9837, 0x9838, 0x9839, 0x983a, 0x983b, 0x983c, 0x983d,
-	0x983e, 0x983f, 0x9850, 0x9851, 0x9852, 0x9853, 0x9854, 0x9855, 0x9856, 0x9857, 0x9858,
-	0x9859, 0x985A, 0x985B, 0x985C, 0x985D, 0x985E, 0x985F, 0x9900, 0x9901, 0x9903, 0x9904,
-	0x9905, 0x9906, 0x9907, 0x9908, 0x9909, 0x990A, 0x990B, 0x990C, 0x990D, 0x990E, 0x990F,
-	0x9910, 0x9913, 0x9917, 0x9918, 0x9919, 0x9990, 0x9991, 0x9992, 0x9993, 0x9994, 0x9995,
-	0x9996, 0x9997, 0x9998, 0x9999, 0x999A, 0x999B, 0x999C, 0x999D, 0x99A0, 0x99A2, 0x99A4
-};
-
-static int dri_node_num(const char *dri_node)
-{
-	long num;
-	ssize_t l = strlen(dri_node);
-
-	while (l > 0 && isdigit(dri_node[l - 1]))
-		l--;
-	num = strtol(dri_node + l, NULL, 10);
-	/* Normalize renderDX nodes with cardX nodes. */
-	if (num >= 128)
-		num -= 128;
-	return num;
-}
-
-static int fd_node_num(int fd)
-{
-	char fd_path[64];
-	char dri_node[256];
-	ssize_t dri_node_size;
-
-	snprintf(fd_path, sizeof(fd_path), "/proc/self/fd/%d", fd);
-
-	dri_node_size = readlink(fd_path, dri_node, sizeof(dri_node));
-	if (dri_node_size < 0)
-		return -errno;
-	dri_node[dri_node_size] = '\0';
-	return dri_node_num(dri_node);
-}
-
-#if 0
-static int
-nouveau_getparam(int fd, uint64_t param, uint64_t *value)
-{
-   struct drm_nouveau_getparam getparam = { .param = param, .value = 0 };
-   int ret = drmCommandWriteRead(fd, DRM_NOUVEAU_GETPARAM, &getparam, sizeof(getparam));
-   *value = getparam.value;
-   return ret;
-}
-#endif
-
-/*
- * One would wish we could read .driver_features from DRM driver.
- */
-static int detect_device_info(unsigned int detect_flags, int fd, struct gbm_device_info *info)
-{
-	drmVersionPtr version;
-	drmModeResPtr resources;
-
-	info->dev_type_flags = 0;
-
-	version = drmGetVersion(fd);
-
-	if (!version)
-		return -EINVAL;
-
-	resources = drmModeGetResources(fd);
-	if (resources) {
-		info->connectors = (unsigned int)(resources->count_connectors);
-		if (resources->count_connectors)
-			info->dev_type_flags |= GBM_DEV_TYPE_FLAG_DISPLAY;
-		if (detect_flags & GBM_DETECT_FLAG_CONNECTED) {
-			int c;
-			for (c = 0; c < resources->count_connectors; c++) {
-				drmModeConnectorPtr conn =
-				    drmModeGetConnector(fd, resources->connectors[c]);
-				if (!conn)
-					continue;
-				if (conn->connection == DRM_MODE_CONNECTED)
-					info->connected++;
-				if (conn->connector_type == DRM_MODE_CONNECTOR_eDP ||
-				    conn->connector_type == DRM_MODE_CONNECTOR_LVDS ||
-				    conn->connector_type == DRM_MODE_CONNECTOR_DSI ||
-				    conn->connector_type == DRM_MODE_CONNECTOR_DPI)
-					info->dev_type_flags |= GBM_DEV_TYPE_FLAG_INTERNAL_LCD;
-				drmModeFreeConnector(conn);
-			}
-		}
-		drmModeFreeResources(resources);
-	}
-
-	if (strncmp("i915", version->name, version->name_len) == 0) {
-		/*
-		 * Detect Intel dGPU here when special getparam ioctl is added.
-		 */
-		info->dev_type_flags |= GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_3D;
-	} else if (strncmp("amdgpu", version->name, version->name_len) == 0) {
-		struct drm_amdgpu_info request = { 0 };
-		struct drm_amdgpu_info_device dev_info = { 0 };
-		int ret;
-
-		info->dev_type_flags = GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_3D;
-		request.return_pointer = (uintptr_t)&dev_info;
-		request.return_size = sizeof(dev_info);
-		request.query = AMDGPU_INFO_DEV_INFO;
-
-		ret =
-		    drmCommandWrite(fd, DRM_AMDGPU_INFO, &request, sizeof(struct drm_amdgpu_info));
-
-		if (ret != 0)
-			goto done;
-		if (!(dev_info.ids_flags & AMDGPU_IDS_FLAGS_FUSION))
-			info->dev_type_flags |= GBM_DEV_TYPE_FLAG_DISCRETE;
-
-	} else if (strncmp("radeon", version->name, version->name_len) == 0) {
-		struct drm_radeon_info radinfo = { 0, 0, 0 };
-		int ret;
-		uint32_t value = 0;
-		size_t d;
-
-		info->dev_type_flags |=
-		    GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_3D | GBM_DEV_TYPE_FLAG_DISCRETE;
-		radinfo.request = RADEON_INFO_DEVICE_ID;
-		radinfo.value = (uintptr_t)&value;
-		ret = drmCommandWriteRead(fd, DRM_RADEON_INFO, &radinfo,
-					  sizeof(struct drm_radeon_info));
-		if (ret != 0)
-			goto done;
-
-		for (d = 0; d < (sizeof(radeon_igp_ids) / sizeof(radeon_igp_ids[0])); d++) {
-			if (value == radeon_igp_ids[d]) {
-				info->dev_type_flags &= ~GBM_DEV_TYPE_FLAG_DISCRETE;
-				break;
-			}
-		}
-
-	} else if (strncmp("nvidia", version->name, version->name_len) == 0) {
-		info->dev_type_flags |=
-		    GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_3D | GBM_DEV_TYPE_FLAG_DISCRETE;
-	} else if (strncmp("nouveau", version->name, version->name_len) == 0) {
-		info->dev_type_flags |=
-		    GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_3D | GBM_DEV_TYPE_FLAG_DISCRETE;
-	} else if (strncmp("msm", version->name, version->name_len) == 0) {
-		info->dev_type_flags |=
-		    GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_3D | GBM_DEV_TYPE_FLAG_ARMSOC;
-	} else if (strncmp("armada", version->name, version->name_len) == 0) {
-		info->dev_type_flags |= GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_ARMSOC;
-	} else if (strncmp("exynos", version->name, version->name_len) == 0) {
-		info->dev_type_flags |= GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_ARMSOC;
-	} else if (strncmp("mediatek", version->name, version->name_len) == 0) {
-		info->dev_type_flags |= GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_ARMSOC;
-	} else if (strncmp("rockchip", version->name, version->name_len) == 0) {
-		info->dev_type_flags |= GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_ARMSOC;
-	} else if (strncmp("omapdrm", version->name, version->name_len) == 0) {
-		info->dev_type_flags |= GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_ARMSOC;
-	} else if (strncmp("vc4", version->name, version->name_len) == 0) {
-		info->dev_type_flags |=
-		    GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_3D | GBM_DEV_TYPE_FLAG_ARMSOC;
-	} else if (strncmp("etnaviv", version->name, version->name_len) == 0) {
-		info->dev_type_flags |= GBM_DEV_TYPE_FLAG_3D | GBM_DEV_TYPE_FLAG_ARMSOC;
-	} else if (strncmp("lima", version->name, version->name_len) == 0) {
-		info->dev_type_flags |= GBM_DEV_TYPE_FLAG_3D | GBM_DEV_TYPE_FLAG_ARMSOC;
-	} else if (strncmp("panfrost", version->name, version->name_len) == 0) {
-		info->dev_type_flags |= GBM_DEV_TYPE_FLAG_3D | GBM_DEV_TYPE_FLAG_ARMSOC;
-	} else if (strncmp("pvr", version->name, version->name_len) == 0) {
-		info->dev_type_flags |= GBM_DEV_TYPE_FLAG_3D | GBM_DEV_TYPE_FLAG_ARMSOC;
-	} else if (strncmp("v3d", version->name, version->name_len) == 0) {
-		info->dev_type_flags |= GBM_DEV_TYPE_FLAG_3D | GBM_DEV_TYPE_FLAG_ARMSOC;
-	} else if (strncmp("vgem", version->name, version->name_len) == 0) {
-		info->dev_type_flags |= GBM_DEV_TYPE_FLAG_BLOCKED;
-	} else if (strncmp("evdi", version->name, version->name_len) == 0) {
-		info->dev_type_flags |=
-		    GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_USB | GBM_DEV_TYPE_FLAG_BLOCKED;
-	} else if (strncmp("udl", version->name, version->name_len) == 0) {
-		info->dev_type_flags |=
-		    GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_USB | GBM_DEV_TYPE_FLAG_BLOCKED;
-	}
-
-done:
-	drmFreeVersion(version);
-	return 0;
-}
-
-PUBLIC int gbm_get_default_device_fd(void)
-{
-	DIR *dir;
-	int ret, fd, dfd = -1;
-	char *rendernode_name;
-	struct dirent *dir_ent;
-	struct gbm_device_info info;
-
-	dir = opendir("/dev/dri");
-	if (!dir)
-		return -errno;
-
-	fd = -1;
-	while ((dir_ent = readdir(dir))) {
-		if (dir_ent->d_type != DT_CHR)
-			continue;
-
-		if (strncmp(dir_ent->d_name, "renderD", 7))
-			continue;
-
-		ret = asprintf(&rendernode_name, "/dev/dri/%s", dir_ent->d_name);
-		if (ret < 0)
-			continue;
-
-		fd = open(rendernode_name, O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK);
-		free(rendernode_name);
-
-		if (fd < 0)
-			continue;
-
-		memset(&info, 0, sizeof(info));
-		if (detect_device_info(0, fd, &info) < 0) {
-			close(fd);
-			fd = -1;
-			continue;
-		}
-
-		if (info.dev_type_flags & GBM_DEV_TYPE_FLAG_BLOCKED) {
-			close(fd);
-			fd = -1;
-			continue;
-		}
-
-		if (!(info.dev_type_flags & GBM_DEV_TYPE_FLAG_DISPLAY)) {
-			close(fd);
-			fd = -1;
-			continue;
-		}
-
-		if (info.dev_type_flags & GBM_DEV_TYPE_FLAG_DISCRETE) {
-			if (dfd < 0)
-				dfd = fd;
-			else
-				close(fd);
-			fd = -1;
-		} else {
-			if (dfd >= 0) {
-				close(dfd);
-				dfd = -1;
-			}
-			break;
-		}
-	}
-	if (dfd >= 0)
-		return dfd;
-
-	return fd;
-}
-
-PUBLIC int gbm_detect_device_info(unsigned int detect_flags, int fd, struct gbm_device_info *info)
-{
-	if (!info)
-		return -EINVAL;
-	memset(info, 0, sizeof(*info));
-	info->dri_node_num = fd_node_num(fd);
-	return detect_device_info(detect_flags, fd, info);
-}
-
-PUBLIC int gbm_detect_device_info_path(unsigned int detect_flags, const char *dev_node,
-				       struct gbm_device_info *info)
-{
-	char rendernode_name[64];
-	int fd;
-	int ret;
-
-	if (!info)
-		return -EINVAL;
-	memset(info, 0, sizeof(*info));
-	info->dri_node_num = dri_node_num(dev_node);
-
-	snprintf(rendernode_name, sizeof(rendernode_name), "/dev/dri/renderD%d",
-		 info->dri_node_num + 128);
-	fd = open(rendernode_name, O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK);
-	if (fd < 0)
-		return -errno;
-	ret = detect_device_info(detect_flags, fd, info);
-	close(fd);
-	return ret;
-}
diff --git a/minigbm_helpers.h b/minigbm_helpers.h
deleted file mode 100644
index 08e6283..0000000
--- a/minigbm_helpers.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2020 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#ifndef _MINIGBM_HELPERS_H_
-#define _MINIGBM_HELPERS_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define GBM_DEV_TYPE_FLAG_DISCRETE (1u << 0)	 /* Discrete GPU. Separate chip, dedicated VRAM. */
-#define GBM_DEV_TYPE_FLAG_DISPLAY (1u << 1)	 /* Device capable of display. */
-#define GBM_DEV_TYPE_FLAG_3D (1u << 2)		 /* Device capable or 3D rendering. */
-#define GBM_DEV_TYPE_FLAG_ARMSOC (1u << 3)	 /* Device on ARM SOC. */
-#define GBM_DEV_TYPE_FLAG_USB (1u << 4)		 /* USB device, udl, evdi. */
-#define GBM_DEV_TYPE_FLAG_BLOCKED (1u << 5)	 /* Unsuitable device e.g. vgem, udl, evdi. */
-#define GBM_DEV_TYPE_FLAG_INTERNAL_LCD (1u << 6) /* Device is driving internal LCD. */
-
-struct gbm_device_info {
-	uint32_t dev_type_flags;
-	int dri_node_num; /* DRI node number (0..63), for easy matching of devices. */
-	unsigned int connectors;
-	unsigned int connected;
-};
-
-#define GBM_DETECT_FLAG_CONNECTED (1u << 0) /* Check if any connectors are connected. SLOW! */
-
-int gbm_detect_device_info(unsigned int detect_flags, int fd, struct gbm_device_info *info);
-int gbm_detect_device_info_path(unsigned int detect_flags, const char *dev_node,
-				struct gbm_device_info *info);
-
-/*
- * Select "default" device to use for graphics memory allocator.
- */
-int gbm_get_default_device_fd(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/msm.c b/msm.c
index 16e781f..fac1fd0 100644
--- a/msm.c
+++ b/msm.c
@@ -7,7 +7,6 @@
 #ifdef DRV_MSM
 
 #include <assert.h>
-#include <dlfcn.h>
 #include <drm_fourcc.h>
 #include <errno.h>
 #include <inttypes.h>
@@ -66,24 +65,6 @@
 	return ALIGN(macrotile_width * macrotile_height, PLANE_SIZE_ALIGN);
 }
 
-static unsigned get_pitch_alignment(struct bo *bo)
-{
-	switch (bo->meta.format) {
-	case DRM_FORMAT_NV12:
-		return VENUS_STRIDE_ALIGN;
-	case DRM_FORMAT_YVU420:
-	case DRM_FORMAT_YVU420_ANDROID:
-		/* TODO other YUV formats? */
-		/* Something (in the video stack?) assumes the U/V planes can use
-		 * half the pitch as the Y plane.. to componsate, double the
-		 * alignment:
-		 */
-		return 2 * DEFAULT_ALIGNMENT;
-	default:
-		return DEFAULT_ALIGNMENT;
-	}
-}
-
 static void msm_calculate_layout(struct bo *bo)
 {
 	uint32_t width, height;
@@ -101,14 +82,11 @@
 		y_stride = ALIGN(width, VENUS_STRIDE_ALIGN);
 		uv_stride = ALIGN(width, VENUS_STRIDE_ALIGN);
 		y_scanline = ALIGN(height, VENUS_SCANLINE_ALIGN * 2);
-		uv_scanline = ALIGN(DIV_ROUND_UP(height, 2),
-				    VENUS_SCANLINE_ALIGN * (bo->meta.tiling ? 2 : 1));
+		uv_scanline = ALIGN(DIV_ROUND_UP(height, 2), VENUS_SCANLINE_ALIGN);
 		y_plane = y_stride * y_scanline;
 		uv_plane = uv_stride * uv_scanline;
 
 		if (bo->meta.tiling == MSM_UBWC_TILING) {
-			y_plane = ALIGN(y_plane, PLANE_SIZE_ALIGN);
-			uv_plane = ALIGN(uv_plane, PLANE_SIZE_ALIGN);
 			y_plane += get_ubwc_meta_size(width, height, 32, 8);
 			uv_plane += get_ubwc_meta_size(width >> 1, height >> 1, 16, 8);
 			extra_padding = NV12_UBWC_PADDING(y_stride);
@@ -126,7 +104,7 @@
 	} else {
 		uint32_t stride, alignw, alignh;
 
-		alignw = ALIGN(width, get_pitch_alignment(bo));
+		alignw = ALIGN(width, DEFAULT_ALIGNMENT);
 		/* HAL_PIXEL_FORMAT_YV12 requires that the buffer's height not be aligned.
 			DRM_FORMAT_R8 of height one is used for JPEG camera output, so don't
 			height align that. */
@@ -179,58 +157,13 @@
 	}
 }
 
-/**
- * Check for buggy apps that are known to not support modifiers, to avoid surprising them
- * with a UBWC buffer.
- */
-static bool should_avoid_ubwc(void)
-{
-#ifndef __ANDROID__
-	/* waffle is buggy and, requests a renderable buffer (which on qcom platforms, we
-	 * want to use UBWC), and then passes it to the kernel discarding the modifier.
-	 * So mesa ends up correctly rendering to as tiled+compressed, but kernel tries
-	 * to display as linear.  Other platforms do not see this issue, simply because
-	 * they only use compressed (ex, AFBC) with the BO_USE_SCANOUT flag.
-	 *
-	 * See b/163137550
-	 */
-	if (dlsym(RTLD_DEFAULT, "waffle_display_connect")) {
-		drv_log("WARNING: waffle detected, disabling UBWC\n");
-		return true;
-	}
-
-	/* The video_decode_accelerator_tests needs to read back the frames
-	 * to verify they are correct.  The frame verification relies on
-	 * computing the MD5 of the video frame.  UBWC results in a different
-	 * MD5.  This turns off UBWC for gtest until a proper frame
-	 * comparison can be made
-	 * Rely on the same mechanism that waffle is using, but this time check
-	 * for a dynamic library function that is present in chrome, but missing
-	 * in gtest.  Cups is not loaded for video tests.
-	 *
-	 * See b/171260705
-	 */
-	if (!dlsym(RTLD_DEFAULT, "cupsFilePrintf")) {
-		drv_log("WARNING: gtest detected, disabling UBWC\n");
-		return true;
-	}
-#endif
-	return false;
-}
-
 static int msm_init(struct driver *drv)
 {
 	struct format_metadata metadata;
 	uint64_t render_use_flags = BO_USE_RENDER_MASK | BO_USE_SCANOUT;
 	uint64_t texture_use_flags = BO_USE_TEXTURE_MASK | BO_USE_HW_VIDEO_DECODER;
-	/*
-	 * NOTE: we actually could use tiled in the BO_USE_FRONT_RENDERING case,
-	 * if we had a modifier for tiled-but-not-compressed.  But we *cannot* use
-	 * compressed in this case because the UBWC flags/meta data can be out of
-	 * sync with pixel data while the GPU is writing a frame out to memory.
-	 */
-	uint64_t sw_flags =
-	    (BO_USE_RENDERSCRIPT | BO_USE_SW_MASK | BO_USE_LINEAR | BO_USE_FRONT_RENDERING);
+	uint64_t sw_flags = (BO_USE_RENDERSCRIPT | BO_USE_SW_WRITE_OFTEN | BO_USE_SW_READ_OFTEN |
+			     BO_USE_LINEAR | BO_USE_PROTECTED);
 
 	drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
 			     &LINEAR_METADATA, render_use_flags);
@@ -238,28 +171,28 @@
 	drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats),
 			     &LINEAR_METADATA, texture_use_flags);
 
-	/* The camera stack standardizes on NV12 for YUV buffers. */
-	/* YVU420 and NV12 formats for camera, display and encoding. */
-	drv_modify_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA,
-			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_SCANOUT |
-				   BO_USE_HW_VIDEO_ENCODER);
+	/*
+	 * Chrome uses DMA-buf mmap to write to YV12 buffers, which are then accessed by the
+	 * Video Encoder Accelerator (VEA). It could also support NV12 potentially in the future.
+	 */
+	drv_modify_combination(drv, DRM_FORMAT_YVU420, &LINEAR_METADATA, BO_USE_HW_VIDEO_ENCODER);
+	drv_modify_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA, BO_USE_HW_VIDEO_ENCODER);
 
+	/* The camera stack standardizes on NV12 for YUV buffers. */
+	drv_modify_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA,
+			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_SCANOUT);
 	/*
 	 * R8 format is used for Android's HAL_PIXEL_FORMAT_BLOB and is used for JPEG snapshots
-	 * from camera and input/output from hardware decoder/encoder.
+	 * from camera.
 	 */
 	drv_modify_combination(drv, DRM_FORMAT_R8, &LINEAR_METADATA,
-			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER |
-				   BO_USE_HW_VIDEO_ENCODER);
+			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
 
 	/* Android CTS tests require this. */
 	drv_add_combination(drv, DRM_FORMAT_BGR888, &LINEAR_METADATA, BO_USE_SW_MASK);
 
 	drv_modify_linear_combinations(drv);
 
-	if (should_avoid_ubwc() || !drv->compression)
-		return 0;
-
 	metadata.tiling = MSM_UBWC_TILING;
 	metadata.priority = 2;
 	metadata.modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
@@ -273,22 +206,21 @@
 	msm_add_ubwc_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats),
 				  &metadata, texture_use_flags);
 
-	drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata,
-			       BO_USE_SCANOUT | BO_USE_HW_VIDEO_ENCODER);
-
 	return 0;
 }
 
 static int msm_bo_create_for_modifier(struct bo *bo, uint32_t width, uint32_t height,
 				      uint32_t format, const uint64_t modifier)
 {
-	struct drm_msm_gem_new req = { 0 };
+	struct drm_msm_gem_new req;
 	int ret;
 	size_t i;
 
 	bo->meta.tiling = (modifier == DRM_FORMAT_MOD_QCOM_COMPRESSED) ? MSM_UBWC_TILING : 0;
+
 	msm_calculate_layout(bo);
 
+	memset(&req, 0, sizeof(req));
 	req.flags = MSM_BO_WC | MSM_BO_SCANOUT;
 	req.size = bo->meta.total_size;
 
@@ -302,10 +234,11 @@
 	 * Though we use only one plane, we need to set handle for
 	 * all planes to pass kernel checks
 	 */
-	for (i = 0; i < bo->meta.num_planes; i++)
+	for (i = 0; i < bo->meta.num_planes; i++) {
 		bo->handles[i].u32 = req.handle;
+		bo->meta.format_modifiers[i] = modifier;
+	}
 
-	bo->meta.format_modifier = modifier;
 	return 0;
 }
 
@@ -320,9 +253,6 @@
 	uint64_t modifier =
 	    drv_pick_modifier(modifiers, count, modifier_order, ARRAY_SIZE(modifier_order));
 
-	if (!bo->drv->compression && modifier == DRM_FORMAT_MOD_QCOM_COMPRESSED)
-		modifier = DRM_FORMAT_MOD_LINEAR;
-
 	return msm_bo_create_for_modifier(bo, width, height, format, modifier);
 }
 
@@ -343,9 +273,11 @@
 static void *msm_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
 {
 	int ret;
-	struct drm_msm_gem_info req = { 0 };
+	struct drm_msm_gem_info req;
 
+	memset(&req, 0, sizeof(req));
 	req.handle = bo->handles[0].u32;
+
 	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MSM_GEM_INFO, &req);
 	if (ret) {
 		drv_log("DRM_IOCLT_MSM_GEM_INFO failed with %s\n", strerror(errno));
@@ -357,6 +289,16 @@
 		    req.offset);
 }
 
+static uint32_t msm_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags)
+{
+	switch (format) {
+	case DRM_FORMAT_FLEX_YCbCr_420_888:
+		return DRM_FORMAT_NV12;
+	default:
+		return format;
+	}
+}
+
 const struct backend backend_msm = {
 	.name = "msm",
 	.init = msm_init,
@@ -366,6 +308,6 @@
 	.bo_import = drv_prime_bo_import,
 	.bo_map = msm_bo_map,
 	.bo_unmap = drv_bo_munmap,
-	.resolve_format = drv_resolve_format_helper,
+	.resolve_format = msm_resolve_format,
 };
 #endif /* DRV_MSM */
diff --git a/nouveau.c b/nouveau.c
new file mode 100644
index 0000000..d0f25d4
--- /dev/null
+++ b/nouveau.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2016 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 };
+
+static int nouveau_init(struct driver *drv)
+{
+	drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+			     &LINEAR_METADATA, BO_USE_RENDER_MASK);
+
+	return drv_modify_linear_combinations(drv);
+}
+
+const struct backend backend_nouveau = {
+	.name = "nouveau",
+	.init = nouveau_init,
+	.bo_create = drv_dumb_bo_create,
+	.bo_destroy = drv_dumb_bo_destroy,
+	.bo_import = drv_prime_bo_import,
+	.bo_map = drv_dumb_bo_map,
+	.bo_unmap = drv_bo_munmap,
+};
diff --git a/presubmit.sh b/presubmit.sh
index 69665f2..5e8a32a 100755
--- a/presubmit.sh
+++ b/presubmit.sh
@@ -4,7 +4,6 @@
 # found in the LICENSE file.
 find \
 	'(' -name '*.[ch]' -or -name '*.cc' ')' \
-	-not -name 'virtgpu_drm.h' -not -name 'i915_drm.h' \
+	-not -name 'virtgpu_drm.h' \
 	-not -name 'gbm.h' -not -name 'virgl_hw.h' \
-	-not -name 'virgl_protocol.h' \
 	-exec clang-format -style=file -i {} +
diff --git a/radeon.c b/radeon.c
new file mode 100644
index 0000000..68445c1
--- /dev/null
+++ b/radeon.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2017 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 };
+
+static int radeon_init(struct driver *drv)
+{
+	drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+			     &LINEAR_METADATA, BO_USE_RENDER_MASK);
+
+	return drv_modify_linear_combinations(drv);
+}
+
+const struct backend backend_radeon = {
+	.name = "radeon",
+	.init = radeon_init,
+	.bo_create = drv_dumb_bo_create,
+	.bo_destroy = drv_dumb_bo_destroy,
+	.bo_import = drv_prime_bo_import,
+	.bo_map = drv_dumb_bo_map,
+	.bo_unmap = drv_bo_munmap,
+};
diff --git a/rockchip.c b/rockchip.c
index 4ef30bc..25f16ab 100644
--- a/rockchip.c
+++ b/rockchip.c
@@ -69,7 +69,7 @@
 
 	bo->meta.total_size = total_size;
 
-	bo->meta.format_modifier = DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC;
+	bo->meta.format_modifiers[0] = DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC;
 
 	return 0;
 }
@@ -88,20 +88,24 @@
 	drv_add_combinations(drv, texture_only_formats, ARRAY_SIZE(texture_only_formats), &metadata,
 			     BO_USE_TEXTURE_MASK);
 
-	/* NV12 format for camera, display, decoding and encoding. */
+	/*
+	 * Chrome uses DMA-buf mmap to write to YV12 buffers, which are then accessed by the
+	 * Video Encoder Accelerator (VEA). It could also support NV12 potentially in the future.
+	 */
+	drv_modify_combination(drv, DRM_FORMAT_YVU420, &metadata, BO_USE_HW_VIDEO_ENCODER);
 	/* Camera ISP supports only NV12 output. */
 	drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata,
-			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_SCANOUT |
-				   BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER);
+			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER |
+				   BO_USE_HW_VIDEO_ENCODER | BO_USE_SCANOUT);
 
 	drv_modify_linear_combinations(drv);
 	/*
 	 * R8 format is used for Android's HAL_PIXEL_FORMAT_BLOB and is used for JPEG snapshots
-	 * from camera and input/output from hardware decoder/encoder.
+	 * from camera.
 	 */
 	drv_add_combination(drv, DRM_FORMAT_R8, &metadata,
 			    BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_SW_MASK |
-				BO_USE_LINEAR | BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER);
+				BO_USE_LINEAR | BO_USE_PROTECTED);
 
 	return 0;
 }
@@ -112,7 +116,7 @@
 {
 	int ret;
 	size_t plane;
-	struct drm_rockchip_gem_create gem_create = { 0 };
+	struct drm_rockchip_gem_create gem_create;
 
 	if (format == DRM_FORMAT_NV12) {
 		uint32_t w_mbs = DIV_ROUND_UP(width, 16);
@@ -128,8 +132,7 @@
 		 */
 		bo->meta.total_size += w_mbs * h_mbs * 128;
 	} else if (width <= 2560 &&
-		   drv_has_modifier(modifiers, count, DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC) &&
-		   bo->drv->compression) {
+		   drv_has_modifier(modifiers, count, DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC)) {
 		/* If the caller has decided they can use AFBC, always
 		 * pick that */
 		afbc_bo_from_format(bo, width, height, format);
@@ -137,7 +140,7 @@
 		if (!drv_has_modifier(modifiers, count, DRM_FORMAT_MOD_LINEAR)) {
 			errno = EINVAL;
 			drv_log("no usable modifier found\n");
-			return -errno;
+			return -1;
 		}
 
 		uint32_t stride;
@@ -156,7 +159,9 @@
 		drv_bo_from_format(bo, stride, height, format);
 	}
 
+	memset(&gem_create, 0, sizeof(gem_create));
 	gem_create.size = bo->meta.total_size;
+
 	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_ROCKCHIP_GEM_CREATE, &gem_create);
 
 	if (ret) {
@@ -182,15 +187,17 @@
 static void *rockchip_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
 {
 	int ret;
+	struct drm_rockchip_gem_map_off gem_map;
 	struct rockchip_private_map_data *priv;
-	struct drm_rockchip_gem_map_off gem_map = { 0 };
 
 	/* We can only map buffers created with SW access flags, which should
 	 * have no modifiers (ie, not AFBC). */
-	if (bo->meta.format_modifier == DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC)
+	if (bo->meta.format_modifiers[0] == DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC)
 		return MAP_FAILED;
 
+	memset(&gem_map, 0, sizeof(gem_map));
 	gem_map.handle = bo->handles[0].u32;
+
 	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_ROCKCHIP_GEM_MAP_OFFSET, &gem_map);
 	if (ret) {
 		drv_log("DRM_IOCTL_ROCKCHIP_GEM_MAP_OFFSET failed\n");
@@ -245,6 +252,22 @@
 	return 0;
 }
 
+static uint32_t rockchip_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags)
+{
+	switch (format) {
+	case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
+		/* Camera subsystem requires NV12. */
+		if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE))
+			return DRM_FORMAT_NV12;
+		/*HACK: See b/28671744 */
+		return DRM_FORMAT_XBGR8888;
+	case DRM_FORMAT_FLEX_YCbCr_420_888:
+		return DRM_FORMAT_NV12;
+	default:
+		return format;
+	}
+}
+
 const struct backend backend_rockchip = {
 	.name = "rockchip",
 	.init = rockchip_init,
@@ -256,7 +279,7 @@
 	.bo_unmap = rockchip_bo_unmap,
 	.bo_invalidate = rockchip_bo_invalidate,
 	.bo_flush = rockchip_bo_flush,
-	.resolve_format = drv_resolve_format_helper,
+	.resolve_format = rockchip_resolve_format,
 };
 
 #endif
diff --git a/synaptics.c b/synaptics.c
new file mode 100644
index 0000000..28cb518
--- /dev/null
+++ b/synaptics.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2020 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifdef DRV_SYNAPTICS
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_ABGR8888,
+                                                  DRM_FORMAT_XRGB8888 };
+
+static const uint32_t texture_source_formats[] = { DRM_FORMAT_R8, DRM_FORMAT_NV12,
+                                                   DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID };
+
+static int synaptics_init(struct driver *drv)
+{
+	drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+			     &LINEAR_METADATA, BO_USE_RENDER_MASK | BO_USE_SCANOUT);
+
+	drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats),
+			     &LINEAR_METADATA, BO_USE_TEXTURE_MASK | BO_USE_HW_VIDEO_ENCODER);
+
+	return drv_modify_linear_combinations(drv);
+}
+
+const struct backend backend_synaptics = {
+	.name = "synaptics",
+	.init = synaptics_init,
+	.bo_create = drv_dumb_bo_create,
+	.bo_destroy = drv_dumb_bo_destroy,
+	.bo_import = drv_prime_bo_import,
+	.bo_map = drv_dumb_bo_map,
+	.bo_unmap = drv_bo_munmap,
+};
+
+#endif
diff --git a/tegra.c b/tegra.c
new file mode 100644
index 0000000..df97461
--- /dev/null
+++ b/tegra.c
@@ -0,0 +1,363 @@
+/*
+ * Copyright 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifdef DRV_TEGRA
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <tegra_drm.h>
+#include <xf86drm.h>
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+/*
+ * GOB (Group Of Bytes) is the basic unit of the blocklinear layout.
+ * GOBs are arranged to blocks, where the height of the block (measured
+ * in GOBs) is configurable.
+ */
+#define NV_BLOCKLINEAR_GOB_HEIGHT 8
+#define NV_BLOCKLINEAR_GOB_WIDTH 64
+#define NV_DEFAULT_BLOCK_HEIGHT_LOG2 4
+#define NV_PREFERRED_PAGE_SIZE (128 * 1024)
+
+// clang-format off
+enum nv_mem_kind
+{
+	NV_MEM_KIND_PITCH = 0,
+	NV_MEM_KIND_C32_2CRA = 0xdb,
+	NV_MEM_KIND_GENERIC_16Bx2 = 0xfe,
+};
+
+enum tegra_map_type {
+	TEGRA_READ_TILED_BUFFER = 0,
+	TEGRA_WRITE_TILED_BUFFER = 1,
+};
+// clang-format on
+
+struct tegra_private_map_data {
+	void *tiled;
+	void *untiled;
+};
+
+static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 };
+
+static int compute_block_height_log2(int height)
+{
+	int block_height_log2 = NV_DEFAULT_BLOCK_HEIGHT_LOG2;
+
+	if (block_height_log2 > 0) {
+		/* Shrink, if a smaller block height could cover the whole
+		 * surface height. */
+		int proposed = NV_BLOCKLINEAR_GOB_HEIGHT << (block_height_log2 - 1);
+		while (proposed >= height) {
+			block_height_log2--;
+			if (block_height_log2 == 0)
+				break;
+			proposed /= 2;
+		}
+	}
+	return block_height_log2;
+}
+
+static void compute_layout_blocklinear(int width, int height, int format, enum nv_mem_kind *kind,
+				       uint32_t *block_height_log2, uint32_t *stride,
+				       uint32_t *size)
+{
+	int pitch = drv_stride_from_format(format, width, 0);
+
+	/* Align to blocklinear blocks. */
+	pitch = ALIGN(pitch, NV_BLOCKLINEAR_GOB_WIDTH);
+
+	/* Compute padded height. */
+	*block_height_log2 = compute_block_height_log2(height);
+	int block_height = 1 << *block_height_log2;
+	int padded_height = ALIGN(height, NV_BLOCKLINEAR_GOB_HEIGHT * block_height);
+
+	int bytes = pitch * padded_height;
+
+	/* Pad the allocation to the preferred page size.
+	 * This will reduce the required page table size (see discussion in NV
+	 * bug 1321091), and also acts as a WAR for NV bug 1325421.
+	 */
+	bytes = ALIGN(bytes, NV_PREFERRED_PAGE_SIZE);
+
+	*kind = NV_MEM_KIND_C32_2CRA;
+	*stride = pitch;
+	*size = bytes;
+}
+
+static void compute_layout_linear(int width, int height, int format, uint32_t *stride,
+				  uint32_t *size)
+{
+	*stride = ALIGN(drv_stride_from_format(format, width, 0), 64);
+	*size = *stride * height;
+}
+
+static void transfer_tile(struct bo *bo, uint8_t *tiled, uint8_t *untiled, enum tegra_map_type type,
+			  uint32_t bytes_per_pixel, uint32_t gob_top, uint32_t gob_left,
+			  uint32_t gob_size_pixels, uint8_t *tiled_last)
+{
+	uint8_t *tmp;
+	uint32_t x, y, k;
+	for (k = 0; k < gob_size_pixels; k++) {
+		/*
+		 * Given the kth pixel starting from the tile specified by
+		 * gob_top and gob_left, unswizzle to get the standard (x, y)
+		 * representation.
+		 */
+		x = gob_left + (((k >> 3) & 8) | ((k >> 1) & 4) | (k & 3));
+		y = gob_top + ((k >> 7 << 3) | ((k >> 3) & 6) | ((k >> 2) & 1));
+
+		if (tiled >= tiled_last)
+			return;
+
+		if (x >= bo->meta.width || y >= bo->meta.height) {
+			tiled += bytes_per_pixel;
+			continue;
+		}
+
+		tmp = untiled + y * bo->meta.strides[0] + x * bytes_per_pixel;
+
+		if (type == TEGRA_READ_TILED_BUFFER)
+			memcpy(tmp, tiled, bytes_per_pixel);
+		else if (type == TEGRA_WRITE_TILED_BUFFER)
+			memcpy(tiled, tmp, bytes_per_pixel);
+
+		/* Move on to next pixel. */
+		tiled += bytes_per_pixel;
+	}
+}
+
+static void transfer_tiled_memory(struct bo *bo, uint8_t *tiled, uint8_t *untiled,
+				  enum tegra_map_type type)
+{
+	uint32_t gob_width, gob_height, gob_size_bytes, gob_size_pixels, gob_count_x, gob_count_y,
+	    gob_top, gob_left;
+	uint32_t i, j, offset;
+	uint8_t *tmp, *tiled_last;
+	uint32_t bytes_per_pixel = drv_stride_from_format(bo->meta.format, 1, 0);
+
+	/*
+	 * The blocklinear format consists of 8*(2^n) x 64 byte sized tiles,
+	 * where 0 <= n <= 4.
+	 */
+	gob_width = DIV_ROUND_UP(NV_BLOCKLINEAR_GOB_WIDTH, bytes_per_pixel);
+	gob_height = NV_BLOCKLINEAR_GOB_HEIGHT * (1 << NV_DEFAULT_BLOCK_HEIGHT_LOG2);
+	/* Calculate the height from maximum possible gob height */
+	while (gob_height > NV_BLOCKLINEAR_GOB_HEIGHT && gob_height >= 2 * bo->meta.height)
+		gob_height /= 2;
+
+	gob_size_bytes = gob_height * NV_BLOCKLINEAR_GOB_WIDTH;
+	gob_size_pixels = gob_height * gob_width;
+
+	gob_count_x = DIV_ROUND_UP(bo->meta.strides[0], NV_BLOCKLINEAR_GOB_WIDTH);
+	gob_count_y = DIV_ROUND_UP(bo->meta.height, gob_height);
+
+	tiled_last = tiled + bo->meta.total_size;
+
+	offset = 0;
+	for (j = 0; j < gob_count_y; j++) {
+		gob_top = j * gob_height;
+		for (i = 0; i < gob_count_x; i++) {
+			tmp = tiled + offset;
+			gob_left = i * gob_width;
+
+			transfer_tile(bo, tmp, untiled, type, bytes_per_pixel, gob_top, gob_left,
+				      gob_size_pixels, tiled_last);
+
+			offset += gob_size_bytes;
+		}
+	}
+}
+
+static int tegra_init(struct driver *drv)
+{
+	struct format_metadata metadata;
+	uint64_t use_flags = BO_USE_RENDER_MASK;
+
+	metadata.tiling = NV_MEM_KIND_PITCH;
+	metadata.priority = 1;
+	metadata.modifier = DRM_FORMAT_MOD_LINEAR;
+
+	drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+			     &metadata, use_flags);
+
+	drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT);
+	drv_modify_combination(drv, DRM_FORMAT_ARGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT);
+
+	use_flags &= ~BO_USE_SW_WRITE_OFTEN;
+	use_flags &= ~BO_USE_SW_READ_OFTEN;
+	use_flags &= ~BO_USE_LINEAR;
+
+	metadata.tiling = NV_MEM_KIND_C32_2CRA;
+	metadata.priority = 2;
+
+	drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+			     &metadata, use_flags);
+
+	drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_SCANOUT);
+	drv_modify_combination(drv, DRM_FORMAT_ARGB8888, &metadata, BO_USE_SCANOUT);
+	return 0;
+}
+
+static int tegra_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+			   uint64_t use_flags)
+{
+	uint32_t size, stride, block_height_log2 = 0;
+	enum nv_mem_kind kind = NV_MEM_KIND_PITCH;
+	struct drm_tegra_gem_create gem_create;
+	int ret;
+
+	if (use_flags &
+	    (BO_USE_CURSOR | BO_USE_LINEAR | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN))
+		compute_layout_linear(width, height, format, &stride, &size);
+	else
+		compute_layout_blocklinear(width, height, format, &kind, &block_height_log2,
+					   &stride, &size);
+
+	memset(&gem_create, 0, sizeof(gem_create));
+	gem_create.size = size;
+	gem_create.flags = 0;
+
+	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_TEGRA_GEM_CREATE, &gem_create);
+	if (ret) {
+		drv_log("DRM_IOCTL_TEGRA_GEM_CREATE failed (size=%zu)\n", size);
+		return -errno;
+	}
+
+	bo->handles[0].u32 = gem_create.handle;
+	bo->meta.offsets[0] = 0;
+	bo->meta.total_size = bo->meta.sizes[0] = size;
+	bo->meta.strides[0] = stride;
+
+	if (kind != NV_MEM_KIND_PITCH) {
+		struct drm_tegra_gem_set_tiling gem_tile;
+
+		memset(&gem_tile, 0, sizeof(gem_tile));
+		gem_tile.handle = bo->handles[0].u32;
+		gem_tile.mode = DRM_TEGRA_GEM_TILING_MODE_BLOCK;
+		gem_tile.value = block_height_log2;
+
+		ret = drmCommandWriteRead(bo->drv->fd, DRM_TEGRA_GEM_SET_TILING, &gem_tile,
+					  sizeof(gem_tile));
+		if (ret < 0) {
+			drv_gem_bo_destroy(bo);
+			return ret;
+		}
+
+		/* Encode blocklinear parameters for EGLImage creation. */
+		bo->meta.tiling = (kind & 0xff) | ((block_height_log2 & 0xf) << 8);
+		bo->meta.format_modifiers[0] = fourcc_mod_code(NV, bo->meta.tiling);
+	}
+
+	return 0;
+}
+
+static int tegra_bo_import(struct bo *bo, struct drv_import_fd_data *data)
+{
+	int ret;
+	struct drm_tegra_gem_get_tiling gem_get_tiling;
+
+	ret = drv_prime_bo_import(bo, data);
+	if (ret)
+		return ret;
+
+	/* TODO(gsingh): export modifiers and get rid of backdoor tiling. */
+	memset(&gem_get_tiling, 0, sizeof(gem_get_tiling));
+	gem_get_tiling.handle = bo->handles[0].u32;
+
+	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_TEGRA_GEM_GET_TILING, &gem_get_tiling);
+	if (ret) {
+		drv_gem_bo_destroy(bo);
+		return -errno;
+	}
+
+	/* NOTE(djmk): we only know about one tiled format, so if our drmIoctl call tells us we are
+	   tiled, assume it is this format (NV_MEM_KIND_C32_2CRA) otherwise linear (KIND_PITCH). */
+	if (gem_get_tiling.mode == DRM_TEGRA_GEM_TILING_MODE_PITCH) {
+		bo->meta.tiling = NV_MEM_KIND_PITCH;
+	} else if (gem_get_tiling.mode == DRM_TEGRA_GEM_TILING_MODE_BLOCK) {
+		bo->meta.tiling = NV_MEM_KIND_C32_2CRA;
+	} else {
+		drv_log("%s: unknown tile format %d\n", __func__, gem_get_tiling.mode);
+		drv_gem_bo_destroy(bo);
+		assert(0);
+	}
+
+	bo->meta.format_modifiers[0] = fourcc_mod_code(NV, bo->meta.tiling);
+	return 0;
+}
+
+static void *tegra_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
+{
+	int ret;
+	struct drm_tegra_gem_mmap gem_map;
+	struct tegra_private_map_data *priv;
+
+	memset(&gem_map, 0, sizeof(gem_map));
+	gem_map.handle = bo->handles[0].u32;
+
+	ret = drmCommandWriteRead(bo->drv->fd, DRM_TEGRA_GEM_MMAP, &gem_map, sizeof(gem_map));
+	if (ret < 0) {
+		drv_log("DRM_TEGRA_GEM_MMAP failed\n");
+		return MAP_FAILED;
+	}
+
+	void *addr = mmap(0, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd,
+			  gem_map.offset);
+	vma->length = bo->meta.total_size;
+	if ((bo->meta.tiling & 0xFF) == NV_MEM_KIND_C32_2CRA && addr != MAP_FAILED) {
+		priv = calloc(1, sizeof(*priv));
+		priv->untiled = calloc(1, bo->meta.total_size);
+		priv->tiled = addr;
+		vma->priv = priv;
+		transfer_tiled_memory(bo, priv->tiled, priv->untiled, TEGRA_READ_TILED_BUFFER);
+		addr = priv->untiled;
+	}
+
+	return addr;
+}
+
+static int tegra_bo_unmap(struct bo *bo, struct vma *vma)
+{
+	if (vma->priv) {
+		struct tegra_private_map_data *priv = vma->priv;
+		vma->addr = priv->tiled;
+		free(priv->untiled);
+		free(priv);
+		vma->priv = NULL;
+	}
+
+	return munmap(vma->addr, vma->length);
+}
+
+static int tegra_bo_flush(struct bo *bo, struct mapping *mapping)
+{
+	struct tegra_private_map_data *priv = mapping->vma->priv;
+
+	if (priv && (mapping->vma->map_flags & BO_MAP_WRITE))
+		transfer_tiled_memory(bo, priv->tiled, priv->untiled, TEGRA_WRITE_TILED_BUFFER);
+
+	return 0;
+}
+
+const struct backend backend_tegra = {
+	.name = "tegra",
+	.init = tegra_init,
+	.bo_create = tegra_bo_create,
+	.bo_destroy = drv_gem_bo_destroy,
+	.bo_import = tegra_bo_import,
+	.bo_map = tegra_bo_map,
+	.bo_unmap = tegra_bo_unmap,
+	.bo_flush = tegra_bo_flush,
+};
+
+#endif
diff --git a/udl.c b/udl.c
new file mode 100644
index 0000000..12dc967
--- /dev/null
+++ b/udl.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 };
+
+static int udl_init(struct driver *drv)
+{
+	drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+			     &LINEAR_METADATA, BO_USE_RENDER_MASK);
+
+	return drv_modify_linear_combinations(drv);
+}
+
+const struct backend backend_udl = {
+	.name = "udl",
+	.init = udl_init,
+	.bo_create = drv_dumb_bo_create,
+	.bo_destroy = drv_dumb_bo_destroy,
+	.bo_import = drv_prime_bo_import,
+	.bo_map = drv_dumb_bo_map,
+	.bo_unmap = drv_bo_munmap,
+};
diff --git a/vc4.c b/vc4.c
index 5ea4bc3..06b3ed7 100644
--- a/vc4.c
+++ b/vc4.c
@@ -20,23 +20,11 @@
 static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_RGB565,
 						  DRM_FORMAT_XRGB8888 };
 
-static const uint32_t texture_only_formats[] = { DRM_FORMAT_NV12, DRM_FORMAT_YVU420 };
-
 static int vc4_init(struct driver *drv)
 {
 	drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
 			     &LINEAR_METADATA, BO_USE_RENDER_MASK);
 
-	drv_add_combinations(drv, texture_only_formats, ARRAY_SIZE(texture_only_formats),
-			     &LINEAR_METADATA, BO_USE_TEXTURE_MASK);
-	/*
-	 * Chrome uses DMA-buf mmap to write to YV12 buffers, which are then accessed by the
-	 * Video Encoder Accelerator (VEA). It could also support NV12 potentially in the future.
-	 */
-	drv_modify_combination(drv, DRM_FORMAT_YVU420, &LINEAR_METADATA, BO_USE_HW_VIDEO_ENCODER);
-	drv_modify_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA,
-			       BO_USE_HW_VIDEO_DECODER | BO_USE_SCANOUT | BO_USE_HW_VIDEO_ENCODER);
-
 	return drv_modify_linear_combinations(drv);
 }
 
@@ -46,7 +34,7 @@
 	int ret;
 	size_t plane;
 	uint32_t stride;
-	struct drm_vc4_create_bo bo_create = { 0 };
+	struct drm_vc4_create_bo bo_create;
 
 	switch (modifier) {
 	case DRM_FORMAT_MOD_LINEAR:
@@ -66,11 +54,12 @@
 	stride = ALIGN(stride, 64);
 	drv_bo_from_format(bo, stride, height, format);
 
+	memset(&bo_create, 0, sizeof(bo_create));
 	bo_create.size = bo->meta.total_size;
 
 	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VC4_CREATE_BO, &bo_create);
 	if (ret) {
-		drv_log("DRM_IOCTL_VC4_CREATE_BO failed (size=%zu)\n", bo->meta.total_size);
+		drv_log("DRM_IOCTL_VC4_GEM_CREATE failed (size=%zu)\n", bo->meta.total_size);
 		return -errno;
 	}
 
@@ -108,9 +97,11 @@
 static void *vc4_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
 {
 	int ret;
-	struct drm_vc4_mmap_bo bo_map = { 0 };
+	struct drm_vc4_mmap_bo bo_map;
 
+	memset(&bo_map, 0, sizeof(bo_map));
 	bo_map.handle = bo->handles[0].u32;
+
 	ret = drmCommandWriteRead(bo->drv->fd, DRM_VC4_MMAP_BO, &bo_map, sizeof(bo_map));
 	if (ret) {
 		drv_log("DRM_VC4_MMAP_BO failed\n");
diff --git a/vgem.c b/vgem.c
new file mode 100644
index 0000000..0d0371c
--- /dev/null
+++ b/vgem.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2016 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+#define MESA_LLVMPIPE_TILE_ORDER 6
+#define MESA_LLVMPIPE_TILE_SIZE (1 << MESA_LLVMPIPE_TILE_ORDER)
+
+static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888,
+						  DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888,
+						  DRM_FORMAT_XRGB8888 };
+
+static const uint32_t texture_source_formats[] = { DRM_FORMAT_R8, DRM_FORMAT_YVU420,
+						   DRM_FORMAT_YVU420_ANDROID };
+
+static int vgem_init(struct driver *drv)
+{
+	drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+			     &LINEAR_METADATA, BO_USE_RENDER_MASK);
+
+	drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats),
+			     &LINEAR_METADATA, BO_USE_TEXTURE_MASK);
+
+	return drv_modify_linear_combinations(drv);
+}
+
+static int vgem_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+			  uint64_t flags)
+{
+	width = ALIGN(width, MESA_LLVMPIPE_TILE_SIZE);
+	height = ALIGN(height, MESA_LLVMPIPE_TILE_SIZE);
+
+	return drv_dumb_bo_create(bo, width, height, format, flags);
+}
+
+static uint32_t vgem_resolve_format(struct driver *drv, uint32_t format, uint64_t flags)
+{
+	switch (format) {
+	case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
+		/*HACK: See b/28671744 */
+		return DRM_FORMAT_XBGR8888;
+	case DRM_FORMAT_FLEX_YCbCr_420_888:
+		return DRM_FORMAT_YVU420;
+	default:
+		return format;
+	}
+}
+
+const struct backend backend_vgem = {
+	.name = "vgem",
+	.init = vgem_init,
+	.bo_create = vgem_bo_create,
+	.bo_destroy = drv_dumb_bo_destroy,
+	.bo_import = drv_prime_bo_import,
+	.bo_map = drv_dumb_bo_map,
+	.bo_unmap = drv_bo_munmap,
+	.resolve_format = vgem_resolve_format,
+};
diff --git a/external/virgl_hw.h b/virgl_hw.h
similarity index 96%
rename from external/virgl_hw.h
rename to virgl_hw.h
index 7f4a63f..1c493d1 100644
--- a/external/virgl_hw.h
+++ b/virgl_hw.h
@@ -290,18 +290,6 @@
 
 #define VIRGL_BIND_LINEAR (1 << 22)
 
-#define VIRGL_BIND_SHARED_SUBFLAGS (0xff << 24)
-
-#define VIRGL_BIND_MINIGBM_CAMERA_WRITE (1 << 24)
-#define VIRGL_BIND_MINIGBM_CAMERA_READ (1 << 25)
-#define VIRGL_BIND_MINIGBM_HW_VIDEO_DECODER (1 << 26)
-#define VIRGL_BIND_MINIGBM_HW_VIDEO_ENCODER (1 << 27)
-#define VIRGL_BIND_MINIGBM_SW_READ_OFTEN (1 << 28)
-#define VIRGL_BIND_MINIGBM_SW_READ_RARELY (1 << 29)
-#define VIRGL_BIND_MINIGBM_SW_WRITE_OFTEN (1 << 30)
-#define VIRGL_BIND_MINIGBM_SW_WRITE_RARELY (1 << 31)
-#define VIRGL_BIND_MINIGBM_PROTECTED (0xf << 28) // Mutually exclusive with SW_ flags
-
 struct virgl_caps_bool_set1 {
         unsigned indep_blend_enable:1;
         unsigned indep_blend_func:1;
diff --git a/virtgpu.c b/virtgpu.c
deleted file mode 100644
index 23e90b3..0000000
--- a/virtgpu.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2021 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include <errno.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <xf86drm.h>
-
-#include "drv_priv.h"
-#include "external/virtgpu_drm.h"
-#include "helpers.h"
-#include "util.h"
-#include "virtgpu.h"
-
-#define PARAM(x)                                                                                   \
-	(struct virtgpu_param)                                                                     \
-	{                                                                                          \
-		x, #x, 0                                                                           \
-	}
-
-struct virtgpu_param params[] = {
-	PARAM(VIRTGPU_PARAM_3D_FEATURES),	   PARAM(VIRTGPU_PARAM_CAPSET_QUERY_FIX),
-	PARAM(VIRTGPU_PARAM_RESOURCE_BLOB),	   PARAM(VIRTGPU_PARAM_HOST_VISIBLE),
-	PARAM(VIRTGPU_PARAM_CROSS_DEVICE),	   PARAM(VIRTGPU_PARAM_CONTEXT_INIT),
-	PARAM(VIRTGPU_PARAM_SUPPORTED_CAPSET_IDs), PARAM(VIRTGPU_PARAM_CREATE_GUEST_HANDLE),
-	PARAM(VIRTGPU_PARAM_RESOURCE_SYNC),	   PARAM(VIRTGPU_PARAM_GUEST_VRAM),
-};
-
-extern const struct backend virtgpu_virgl;
-extern const struct backend virtgpu_cross_domain;
-
-static int virtgpu_init(struct driver *drv)
-{
-	int ret = 0;
-	const struct backend *virtgpu_backends[2] = {
-		&virtgpu_cross_domain,
-		&virtgpu_virgl,
-	};
-
-	for (uint32_t i = 0; i < ARRAY_SIZE(params); i++) {
-		struct drm_virtgpu_getparam get_param = { 0 };
-
-		get_param.param = params[i].param;
-		get_param.value = (uint64_t)(uintptr_t)&params[i].value;
-		int ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GETPARAM, &get_param);
-		if (ret)
-			drv_log("DRM_IOCTL_VIRTGPU_GET_PARAM failed with %s\n", strerror(errno));
-	}
-
-	for (uint32_t i = 0; i < ARRAY_SIZE(virtgpu_backends); i++) {
-		const struct backend *backend = virtgpu_backends[i];
-		ret = backend->init(drv);
-		if (ret)
-			continue;
-
-		drv->backend = backend;
-		return 0;
-	}
-
-	return ret;
-}
-
-const struct backend backend_virtgpu = {
-	.name = "virtio_gpu",
-	.init = virtgpu_init,
-};
diff --git a/virtgpu.h b/virtgpu.h
deleted file mode 100644
index 3f68731..0000000
--- a/virtgpu.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2021 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-struct virtgpu_param {
-	uint64_t param;
-	const char *name;
-	uint32_t value;
-};
-
-enum virtgpu_param_id {
-	param_3d,
-	param_capset_fix,
-	param_resource_blob,
-	param_host_visible,
-	param_cross_device,
-	param_context_init,
-	param_supported_capset_ids,
-	param_create_guest_handle,
-	param_resource_sync,
-	param_guest_vram,
-	param_max,
-};
diff --git a/virtgpu_cross_domain.c b/virtgpu_cross_domain.c
deleted file mode 100644
index b02a949..0000000
--- a/virtgpu_cross_domain.c
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- * Copyright 2021 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include <errno.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <xf86drm.h>
-
-#include "drv_priv.h"
-#include "external/virtgpu_cross_domain_protocol.h"
-#include "external/virtgpu_drm.h"
-#include "helpers.h"
-#include "util.h"
-#include "virtgpu.h"
-
-#define CAPSET_CROSS_DOMAIN 5
-#define CAPSET_CROSS_FAKE 30
-
-static const uint32_t scanout_render_formats[] = { DRM_FORMAT_ABGR2101010, DRM_FORMAT_ABGR8888,
-						   DRM_FORMAT_ARGB2101010, DRM_FORMAT_ARGB8888,
-						   DRM_FORMAT_RGB565,	   DRM_FORMAT_XBGR2101010,
-						   DRM_FORMAT_XBGR8888,	   DRM_FORMAT_XRGB2101010,
-						   DRM_FORMAT_XRGB8888 };
-
-static const uint32_t render_formats[] = { DRM_FORMAT_ABGR16161616F };
-
-static const uint32_t texture_only_formats[] = { DRM_FORMAT_R8, DRM_FORMAT_NV12, DRM_FORMAT_P010,
-						 DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID };
-
-extern struct virtgpu_param params[];
-
-struct cross_domain_private {
-	uint32_t ring_handle;
-	void *ring_addr;
-	struct drv_array *metadata_cache;
-};
-
-static void cross_domain_release_private(struct driver *drv)
-{
-	int ret;
-	struct cross_domain_private *priv = drv->priv;
-	struct drm_gem_close gem_close = { 0 };
-
-	if (priv->ring_addr != MAP_FAILED)
-		munmap(priv->ring_addr, PAGE_SIZE);
-
-	if (priv->ring_handle) {
-		gem_close.handle = priv->ring_handle;
-
-		ret = drmIoctl(drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
-		if (ret) {
-			drv_log("DRM_IOCTL_GEM_CLOSE failed (handle=%x) error %d\n",
-				priv->ring_handle, ret);
-		}
-	}
-
-	drv_array_destroy(priv->metadata_cache);
-	free(priv);
-}
-
-static void add_combinations(struct driver *drv)
-{
-	struct format_metadata metadata;
-
-	// Linear metadata always supported.
-	metadata.tiling = 0;
-	metadata.priority = 1;
-	metadata.modifier = DRM_FORMAT_MOD_LINEAR;
-
-	drv_add_combinations(drv, scanout_render_formats, ARRAY_SIZE(scanout_render_formats),
-			     &metadata, BO_USE_RENDER_MASK | BO_USE_SCANOUT);
-
-	drv_add_combinations(drv, render_formats, ARRAY_SIZE(render_formats), &metadata,
-			     BO_USE_RENDER_MASK);
-
-	drv_add_combinations(drv, texture_only_formats, ARRAY_SIZE(texture_only_formats), &metadata,
-			     BO_USE_TEXTURE_MASK);
-
-	/* Android CTS tests require this. */
-	drv_add_combination(drv, DRM_FORMAT_BGR888, &metadata, BO_USE_SW_MASK);
-
-	drv_modify_combination(drv, DRM_FORMAT_YVU420, &metadata, BO_USE_HW_VIDEO_ENCODER);
-	drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata,
-			       BO_USE_HW_VIDEO_DECODER | BO_USE_SCANOUT | BO_USE_HW_VIDEO_ENCODER);
-
-	/*
-	 * R8 format is used for Android's HAL_PIXEL_FORMAT_BLOB and is used for JPEG snapshots
-	 * from camera and input/output from hardware decoder/encoder.
-	 */
-	drv_modify_combination(drv, DRM_FORMAT_R8, &metadata,
-			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER |
-				   BO_USE_HW_VIDEO_ENCODER);
-
-	drv_modify_linear_combinations(drv);
-}
-
-static int cross_domain_submit_cmd(struct driver *drv, uint32_t *cmd, uint32_t cmd_size, bool wait)
-{
-	int ret;
-	struct drm_virtgpu_3d_wait wait_3d = { 0 };
-	struct drm_virtgpu_execbuffer exec = { 0 };
-	struct cross_domain_private *priv = drv->priv;
-
-	exec.command = (uint64_t)&cmd[0];
-	exec.size = cmd_size;
-	if (wait) {
-		exec.flags = VIRTGPU_EXECBUF_FENCE_CONTEXT;
-		exec.bo_handles = (uint64_t)&priv->ring_handle;
-		exec.num_bo_handles = 1;
-	}
-
-	ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_EXECBUFFER, &exec);
-	if (ret < 0) {
-		drv_log("DRM_IOCTL_VIRTGPU_EXECBUFFER failed with %s\n", strerror(errno));
-		return -EINVAL;
-	}
-
-	ret = -EAGAIN;
-	while (ret == -EAGAIN) {
-		wait_3d.handle = priv->ring_handle;
-		ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_WAIT, &wait_3d);
-	}
-
-	if (ret < 0) {
-		drv_log("DRM_IOCTL_VIRTGPU_WAIT failed with %s\n", strerror(errno));
-		return ret;
-	}
-
-	return 0;
-}
-
-static bool metadata_equal(struct bo_metadata *current, struct bo_metadata *cached)
-{
-	if ((current->width == cached->width) && (current->height == cached->height) &&
-	    (current->format == cached->format) && (current->use_flags == cached->use_flags))
-		return true;
-	return false;
-}
-
-static int cross_domain_metadata_query(struct driver *drv, struct bo_metadata *metadata)
-{
-	int ret = 0;
-	struct bo_metadata *cached_data = NULL;
-	struct cross_domain_private *priv = drv->priv;
-	struct CrossDomainGetImageRequirements cmd_get_reqs;
-	uint32_t *addr = (uint32_t *)priv->ring_addr;
-	uint32_t plane, remaining_size;
-
-	memset(&cmd_get_reqs, 0, sizeof(cmd_get_reqs));
-	pthread_mutex_lock(&drv->driver_lock);
-	for (uint32_t i = 0; i < drv_array_size(priv->metadata_cache); i++) {
-		cached_data = (struct bo_metadata *)drv_array_at_idx(priv->metadata_cache, i);
-		if (!metadata_equal(metadata, cached_data))
-			continue;
-
-		memcpy(metadata, cached_data, sizeof(*cached_data));
-		goto out_unlock;
-	}
-
-	cmd_get_reqs.hdr.cmd = CROSS_DOMAIN_CMD_GET_IMAGE_REQUIREMENTS;
-	cmd_get_reqs.hdr.cmd_size = sizeof(struct CrossDomainGetImageRequirements);
-
-	cmd_get_reqs.width = metadata->width;
-	cmd_get_reqs.height = metadata->height;
-	cmd_get_reqs.drm_format =
-	    (metadata->format == DRM_FORMAT_YVU420_ANDROID) ? DRM_FORMAT_YVU420 : metadata->format;
-	cmd_get_reqs.flags = metadata->use_flags;
-
-	/*
-	 * It is possible to avoid blocking other bo_create() calls by unlocking before
-	 * cross_domain_submit_cmd() and re-locking afterwards.  However, that would require
-	 * another scan of the metadata cache before drv_array_append in case two bo_create() calls
-	 * do the same metadata query.  Until cross_domain functionality is more widely tested,
-	 * leave this optimization out for now.
-	 */
-	ret = cross_domain_submit_cmd(drv, (uint32_t *)&cmd_get_reqs, cmd_get_reqs.hdr.cmd_size,
-				      true);
-	if (ret < 0)
-		goto out_unlock;
-
-	memcpy(&metadata->strides, &addr[0], 4 * sizeof(uint32_t));
-	memcpy(&metadata->offsets, &addr[4], 4 * sizeof(uint32_t));
-	memcpy(&metadata->format_modifier, &addr[8], sizeof(uint64_t));
-	memcpy(&metadata->total_size, &addr[10], sizeof(uint64_t));
-	memcpy(&metadata->blob_id, &addr[12], sizeof(uint64_t));
-
-	metadata->map_info = addr[14];
-	metadata->memory_idx = addr[16];
-	metadata->physical_device_idx = addr[17];
-
-	remaining_size = metadata->total_size;
-	for (plane = 0; plane < metadata->num_planes; plane++) {
-		if (plane != 0) {
-			metadata->sizes[plane - 1] = metadata->offsets[plane];
-			remaining_size -= metadata->offsets[plane];
-		}
-	}
-
-	metadata->sizes[plane - 1] = remaining_size;
-	drv_array_append(priv->metadata_cache, metadata);
-
-out_unlock:
-	pthread_mutex_unlock(&drv->driver_lock);
-	return ret;
-}
-
-static int cross_domain_init(struct driver *drv)
-{
-	int ret;
-	struct cross_domain_private *priv;
-	struct drm_virtgpu_map map = { 0 };
-	struct drm_virtgpu_get_caps args = { 0 };
-	struct drm_virtgpu_context_init init = { 0 };
-	struct drm_virtgpu_resource_create_blob drm_rc_blob = { 0 };
-	struct drm_virtgpu_context_set_param ctx_set_params[2] = { { 0 } };
-
-	struct CrossDomainInit cmd_init;
-	struct CrossDomainCapabilities cross_domain_caps;
-
-	memset(&cmd_init, 0, sizeof(cmd_init));
-	if (!params[param_context_init].value)
-		return -ENOTSUP;
-
-	if ((params[param_supported_capset_ids].value & (1 << CAPSET_CROSS_DOMAIN)) == 0)
-		return -ENOTSUP;
-
-	if (!params[param_resource_blob].value)
-		return -ENOTSUP;
-
-	/// Need zero copy memory
-	if (!params[param_host_visible].value && !params[param_create_guest_handle].value)
-		return -ENOTSUP;
-
-	/*
-	 * crosvm never reports the fake capset.  This is just an extra check to make sure we
-	 * don't use the cross-domain context by accident.  Developers may remove this for
-	 * testing purposes.
-	 */
-	if ((params[param_supported_capset_ids].value & (1 << CAPSET_CROSS_FAKE)) == 0)
-		return -ENOTSUP;
-
-	priv = calloc(1, sizeof(*priv));
-	priv->metadata_cache = drv_array_init(sizeof(struct bo_metadata));
-	priv->ring_addr = MAP_FAILED;
-	drv->priv = priv;
-
-	args.cap_set_id = CAPSET_CROSS_DOMAIN;
-	args.size = sizeof(struct CrossDomainCapabilities);
-	args.addr = (unsigned long long)&cross_domain_caps;
-
-	ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GET_CAPS, &args);
-	if (ret) {
-		drv_log("DRM_IOCTL_VIRTGPU_GET_CAPS failed with %s\n", strerror(errno));
-		goto free_private;
-	}
-
-	// When 3D features are avilable, but the host does not support external memory, fall back
-	// to the virgl minigbm backend.  This typically means the guest side minigbm resource will
-	// be backed by a host OpenGL texture.
-	if (!cross_domain_caps.supports_external_gpu_memory && params[param_3d].value) {
-		ret = -ENOTSUP;
-		goto free_private;
-	}
-
-	// Intialize the cross domain context.  Create one fence context to wait for metadata
-	// queries.
-	ctx_set_params[0].param = VIRTGPU_CONTEXT_PARAM_CAPSET_ID;
-	ctx_set_params[0].value = CAPSET_CROSS_DOMAIN;
-	ctx_set_params[1].param = VIRTGPU_CONTEXT_PARAM_NUM_FENCE_CONTEXTS;
-	ctx_set_params[1].value = 1;
-
-	init.ctx_set_params = (unsigned long long)&ctx_set_params[0];
-	init.num_params = 2;
-	ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_CONTEXT_INIT, &init);
-	if (ret) {
-		drv_log("DRM_IOCTL_VIRTGPU_CONTEXT_INIT failed with %s\n", strerror(errno));
-		goto free_private;
-	}
-
-	// Create a shared ring buffer to read metadata queries.
-	drm_rc_blob.size = PAGE_SIZE;
-	drm_rc_blob.blob_mem = VIRTGPU_BLOB_MEM_GUEST;
-	drm_rc_blob.blob_flags = VIRTGPU_BLOB_FLAG_USE_MAPPABLE;
-
-	ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB, &drm_rc_blob);
-	if (ret < 0) {
-		drv_log("DRM_VIRTGPU_RESOURCE_CREATE_BLOB failed with %s\n", strerror(errno));
-		goto free_private;
-	}
-
-	priv->ring_handle = drm_rc_blob.bo_handle;
-
-	// Map shared ring buffer.
-	map.handle = priv->ring_handle;
-	ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_MAP, &map);
-	if (ret < 0) {
-		drv_log("DRM_IOCTL_VIRTGPU_MAP failed with %s\n", strerror(errno));
-		goto free_private;
-	}
-
-	priv->ring_addr =
-	    mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, drv->fd, map.offset);
-
-	if (priv->ring_addr == MAP_FAILED) {
-		drv_log("mmap failed with %s\n", strerror(errno));
-		goto free_private;
-	}
-
-	// Notify host about ring buffer
-	cmd_init.hdr.cmd = CROSS_DOMAIN_CMD_INIT;
-	cmd_init.hdr.cmd_size = sizeof(struct CrossDomainInit);
-	cmd_init.ring_id = drm_rc_blob.res_handle;
-	ret = cross_domain_submit_cmd(drv, (uint32_t *)&cmd_init, cmd_init.hdr.cmd_size, false);
-	if (ret < 0)
-		goto free_private;
-
-	// minigbm bookkeeping
-	add_combinations(drv);
-	return 0;
-
-free_private:
-	cross_domain_release_private(drv);
-	return ret;
-}
-
-static void cross_domain_close(struct driver *drv)
-{
-	cross_domain_release_private(drv);
-}
-
-static int cross_domain_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
-				  uint64_t use_flags)
-{
-	int ret;
-	uint32_t blob_flags = VIRTGPU_BLOB_FLAG_USE_SHAREABLE;
-	struct drm_virtgpu_resource_create_blob drm_rc_blob = { 0 };
-
-	ret = cross_domain_metadata_query(bo->drv, &bo->meta);
-	if (ret < 0) {
-		drv_log("Metadata query failed");
-		return ret;
-	}
-
-	if (use_flags & BO_USE_SW_MASK)
-		blob_flags |= VIRTGPU_BLOB_FLAG_USE_MAPPABLE;
-
-	if (params[param_cross_device].value && (use_flags & BO_USE_NON_GPU_HW))
-		blob_flags |= VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE;
-
-	/// It may be possible to have host3d blobs and handles from guest memory at the same time.
-	/// But for the immediate use cases, we will either have one or the other.  For now, just
-	/// prefer guest memory since adding that feature is more involved (requires --udmabuf
-	/// flag to crosvm), so developers would likely test that.
-	if (params[param_create_guest_handle].value) {
-		drm_rc_blob.blob_mem = VIRTGPU_BLOB_MEM_GUEST;
-		blob_flags |= VIRTGPU_BLOB_FLAG_CREATE_GUEST_HANDLE;
-	} else if (params[param_host_visible].value) {
-		drm_rc_blob.blob_mem = VIRTGPU_BLOB_MEM_HOST3D;
-	}
-
-	drm_rc_blob.size = bo->meta.total_size;
-	drm_rc_blob.blob_flags = blob_flags;
-	drm_rc_blob.blob_id = bo->meta.blob_id;
-
-	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB, &drm_rc_blob);
-	if (ret < 0) {
-		drv_log("DRM_VIRTGPU_RESOURCE_CREATE_BLOB failed with %s\n", strerror(errno));
-		return -errno;
-	}
-
-	for (uint32_t plane = 0; plane < bo->meta.num_planes; plane++)
-		bo->handles[plane].u32 = drm_rc_blob.bo_handle;
-
-	return 0;
-}
-
-static void *cross_domain_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
-{
-	int ret;
-	struct drm_virtgpu_map gem_map = { 0 };
-
-	gem_map.handle = bo->handles[0].u32;
-	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_MAP, &gem_map);
-	if (ret) {
-		drv_log("DRM_IOCTL_VIRTGPU_MAP failed with %s\n", strerror(errno));
-		return MAP_FAILED;
-	}
-
-	vma->length = bo->meta.total_size;
-	return mmap(0, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd,
-		    gem_map.offset);
-}
-
-const struct backend virtgpu_cross_domain = {
-	.name = "virtgpu_cross_domain",
-	.init = cross_domain_init,
-	.close = cross_domain_close,
-	.bo_create = cross_domain_bo_create,
-	.bo_import = drv_prime_bo_import,
-	.bo_destroy = drv_gem_bo_destroy,
-	.bo_map = cross_domain_bo_map,
-	.bo_unmap = drv_bo_munmap,
-	.resolve_format = drv_resolve_format_helper,
-};
diff --git a/external/virtgpu_drm.h b/virtgpu_drm.h
similarity index 62%
rename from external/virtgpu_drm.h
rename to virtgpu_drm.h
index 9b46138..a92d764 100644
--- a/external/virtgpu_drm.h
+++ b/virtgpu_drm.h
@@ -46,16 +46,12 @@
 #define DRM_VIRTGPU_TRANSFER_TO_HOST 0x07
 #define DRM_VIRTGPU_WAIT     0x08
 #define DRM_VIRTGPU_GET_CAPS  0x09
-#define DRM_VIRTGPU_RESOURCE_CREATE_BLOB 0x0a
-#define DRM_VIRTGPU_CONTEXT_INIT 0x0b
 
 #define VIRTGPU_EXECBUF_FENCE_FD_IN	0x01
 #define VIRTGPU_EXECBUF_FENCE_FD_OUT	0x02
-#define VIRTGPU_EXECBUF_FENCE_CONTEXT	0x04
 #define VIRTGPU_EXECBUF_FLAGS  (\
 		VIRTGPU_EXECBUF_FENCE_FD_IN |\
 		VIRTGPU_EXECBUF_FENCE_FD_OUT |\
-		VIRTGPU_EXECBUF_FENCE_CONTEXT |\
 		0)
 
 struct drm_virtgpu_map {
@@ -71,20 +67,10 @@
 	__u64 bo_handles;
 	__u32 num_bo_handles;
 	__s32 fence_fd; /* in/out fence fd (see VIRTGPU_EXECBUF_FENCE_FD_IN/OUT) */
-	__u32 fence_ctx_idx;  /* which fence timeline to use */
-	__u32 pad;
 };
 
 #define VIRTGPU_PARAM_3D_FEATURES 1 /* do we have 3D features in the hw */
 #define VIRTGPU_PARAM_CAPSET_QUERY_FIX 2 /* do we have the capset fix */
-#define VIRTGPU_PARAM_RESOURCE_BLOB 3 /* DRM_VIRTGPU_RESOURCE_CREATE_BLOB */
-#define VIRTGPU_PARAM_HOST_VISIBLE 4 /* Host blob resources are mappable */
-#define VIRTGPU_PARAM_CROSS_DEVICE 5 /* Cross virtio-device resource sharing  */
-#define VIRTGPU_PARAM_CONTEXT_INIT 6 /* DRM_VIRTGPU_CONTEXT_INIT */
-#define VIRTGPU_PARAM_SUPPORTED_CAPSET_IDs 7 /* Bitmask of supported capability set ids */
-#define VIRTGPU_PARAM_CREATE_GUEST_HANDLE 8 /* Host OS handle can be created from guest memory. */
-#define VIRTGPU_PARAM_RESOURCE_SYNC 9 /* Synchronization resources */
-#define VIRTGPU_PARAM_GUEST_VRAM 10 /* All guest allocations happen via virtgpu dedicated heap. */
 
 struct drm_virtgpu_getparam {
 	__u64 param;
@@ -114,24 +100,7 @@
 	__u32 bo_handle;
 	__u32 res_handle;
 	__u32 size;
-	__u32 blob_mem;
-};
-
-/* CHROMIUM */
-struct drm_virtgpu_resource_info_cros {
-	__u32 bo_handle;
-	__u32 res_handle;
-	__u32 size;
-
-/* Return res_handle and size.  Return extended info (strides, num_planes,
- * etc.) until chromeos-5.4 and return blob_mem since chromeos-5.10.
- */
-#define VIRTGPU_RESOURCE_INFO_TYPE_DEFAULT 0
-/* Return res_handle, size, and extended info */
-#define VIRTGPU_RESOURCE_INFO_TYPE_EXTENDED 1
 	union {
-		__u32 type; /* in, VIRTGPU_RESOURCE_INFO_TYPE_* */
-		__u32 blob_mem;
 		__u32 stride;
 		__u32 strides[4]; /* strides[0] is accessible with stride. */
 	};
@@ -154,8 +123,6 @@
 	struct drm_virtgpu_3d_box box;
 	__u32 level;
 	__u32 offset;
-	__u32 stride;
-	__u32 layer_stride;
 };
 
 struct drm_virtgpu_3d_transfer_from_host {
@@ -163,8 +130,6 @@
 	struct drm_virtgpu_3d_box box;
 	__u32 level;
 	__u32 offset;
-	__u32 stride;
-	__u32 layer_stride;
 };
 
 #define VIRTGPU_WAIT_NOWAIT 1 /* like it */
@@ -181,48 +146,6 @@
 	__u32 pad;
 };
 
-struct drm_virtgpu_resource_create_blob {
-#define VIRTGPU_BLOB_MEM_GUEST             0x0001
-#define VIRTGPU_BLOB_MEM_HOST3D            0x0002
-#define VIRTGPU_BLOB_MEM_HOST3D_GUEST      0x0003
-
-#define VIRTGPU_BLOB_FLAG_USE_MAPPABLE     0x0001
-#define VIRTGPU_BLOB_FLAG_USE_SHAREABLE    0x0002
-#define VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE 0x0004
-#define VIRTGPU_BLOB_FLAG_CREATE_GUEST_HANDLE 0x0008
-#define VIRTGPU_BLOB_FLAG_CREATE_GUEST_CONTIG 0x0010
-	/* zero is invalid blob_mem */
-	__u32 blob_mem;
-	__u32 blob_flags;
-	__u32 bo_handle;
-	__u32 res_handle;
-	__u64 size;
-
-	/*
-	 * for 3D contexts with VIRTGPU_BLOB_MEM_HOST3D_GUEST and
-	 * VIRTGPU_BLOB_MEM_HOST3D otherwise, must be zero.
-	 */
-	__u32 pad;
-	__u32 cmd_size;
-	__u64 cmd;
-	__u64 blob_id;
-};
-
-#define VIRTGPU_CONTEXT_PARAM_CAPSET_ID           0x0001
-#define VIRTGPU_CONTEXT_PARAM_NUM_FENCE_CONTEXTS  0x0002
-struct drm_virtgpu_context_set_param {
-	__u64 param;
-	__u64 value;
-};
-
-struct drm_virtgpu_context_init {
-	__u32 num_params;
-	__u32 pad;
-
-	/* pointer to drm_virtgpu_context_set_param array */
-	__u64 ctx_set_params;
-};
-
 #define DRM_IOCTL_VIRTGPU_MAP \
 	DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_MAP, struct drm_virtgpu_map)
 
@@ -242,11 +165,6 @@
 	DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_INFO, \
 		 struct drm_virtgpu_resource_info)
 
-/* same ioctl number as DRM_IOCTL_VIRTGPU_RESOURCE_INFO */
-#define DRM_IOCTL_VIRTGPU_RESOURCE_INFO_CROS \
-	DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_INFO, \
-		 struct drm_virtgpu_resource_info_cros)
-
 #define DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST \
 	DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_TRANSFER_FROM_HOST,	\
 		struct drm_virtgpu_3d_transfer_from_host)
@@ -263,14 +181,6 @@
 	DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_GET_CAPS, \
 	struct drm_virtgpu_get_caps)
 
-#define DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB				\
-	DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_CREATE_BLOB,	\
-		struct drm_virtgpu_resource_create_blob)
-
-#define DRM_IOCTL_VIRTGPU_CONTEXT_INIT					\
-	DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_CONTEXT_INIT,		\
-		struct drm_virtgpu_context_init)
-
 #if defined(__cplusplus)
 }
 #endif
diff --git a/virtgpu_virgl.c b/virtgpu_virgl.c
deleted file mode 100644
index 32ca6a1..0000000
--- a/virtgpu_virgl.c
+++ /dev/null
@@ -1,1002 +0,0 @@
-/*
- * Copyright 2017 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <stdatomic.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <xf86drm.h>
-
-#include "drv_priv.h"
-#include "external/virgl_hw.h"
-#include "external/virgl_protocol.h"
-#include "external/virtgpu_drm.h"
-#include "helpers.h"
-#include "util.h"
-#include "virtgpu.h"
-
-#define PIPE_TEXTURE_2D 2
-
-#define MESA_LLVMPIPE_TILE_ORDER 6
-#define MESA_LLVMPIPE_TILE_SIZE (1 << MESA_LLVMPIPE_TILE_ORDER)
-
-static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888,
-						  DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888,
-						  DRM_FORMAT_XRGB8888 };
-
-static const uint32_t dumb_texture_source_formats[] = {
-	DRM_FORMAT_R8,	 DRM_FORMAT_R16,  DRM_FORMAT_YVU420,
-	DRM_FORMAT_NV12, DRM_FORMAT_NV21, DRM_FORMAT_YVU420_ANDROID
-};
-
-static const uint32_t texture_source_formats[] = { DRM_FORMAT_NV12, DRM_FORMAT_NV21,
-						   DRM_FORMAT_R8,   DRM_FORMAT_R16,
-						   DRM_FORMAT_RG88, DRM_FORMAT_YVU420_ANDROID };
-
-extern struct virtgpu_param params[];
-
-struct virgl_priv {
-	int caps_is_v2;
-	union virgl_caps caps;
-	int host_gbm_enabled;
-	atomic_int next_blob_id;
-};
-
-static uint32_t translate_format(uint32_t drm_fourcc)
-{
-	switch (drm_fourcc) {
-	case DRM_FORMAT_BGR888:
-	case DRM_FORMAT_RGB888:
-		return VIRGL_FORMAT_R8G8B8_UNORM;
-	case DRM_FORMAT_XRGB8888:
-		return VIRGL_FORMAT_B8G8R8X8_UNORM;
-	case DRM_FORMAT_ARGB8888:
-		return VIRGL_FORMAT_B8G8R8A8_UNORM;
-	case DRM_FORMAT_XBGR8888:
-		return VIRGL_FORMAT_R8G8B8X8_UNORM;
-	case DRM_FORMAT_ABGR8888:
-		return VIRGL_FORMAT_R8G8B8A8_UNORM;
-	case DRM_FORMAT_ABGR16161616F:
-		return VIRGL_FORMAT_R16G16B16A16_FLOAT;
-	case DRM_FORMAT_RGB565:
-		return VIRGL_FORMAT_B5G6R5_UNORM;
-	case DRM_FORMAT_R8:
-		return VIRGL_FORMAT_R8_UNORM;
-	case DRM_FORMAT_R16:
-		return VIRGL_FORMAT_R16_UNORM;
-	case DRM_FORMAT_RG88:
-		return VIRGL_FORMAT_R8G8_UNORM;
-	case DRM_FORMAT_NV12:
-		return VIRGL_FORMAT_NV12;
-	case DRM_FORMAT_NV21:
-		return VIRGL_FORMAT_NV21;
-	case DRM_FORMAT_YVU420:
-	case DRM_FORMAT_YVU420_ANDROID:
-		return VIRGL_FORMAT_YV12;
-	default:
-		drv_log("Unhandled format:%d\n", drm_fourcc);
-		return 0;
-	}
-}
-
-static bool virgl_bitmask_supports_format(struct virgl_supported_format_mask *supported,
-					  uint32_t drm_format)
-{
-	uint32_t virgl_format = translate_format(drm_format);
-	if (!virgl_format)
-		return false;
-
-	uint32_t bitmask_index = virgl_format / 32;
-	uint32_t bit_index = virgl_format % 32;
-	return supported->bitmask[bitmask_index] & (1 << bit_index);
-}
-
-// The metadata generated here for emulated buffers is slightly different than the metadata
-// generated by drv_bo_from_format. In order to simplify transfers in the flush and invalidate
-// functions below, the emulated buffers are oversized. For example, ignoring stride alignment
-// requirements to demonstrate, a 6x6 YUV420 image buffer might have the following layout from
-// drv_bo_from_format:
-//
-// | Y | Y | Y | Y | Y | Y |
-// | Y | Y | Y | Y | Y | Y |
-// | Y | Y | Y | Y | Y | Y |
-// | Y | Y | Y | Y | Y | Y |
-// | Y | Y | Y | Y | Y | Y |
-// | Y | Y | Y | Y | Y | Y |
-// | U | U | U | U | U | U |
-// | U | U | U | V | V | V |
-// | V | V | V | V | V | V |
-//
-// where each plane immediately follows the previous plane in memory. This layout makes it
-// difficult to compute the transfers needed for example when the middle 2x2 region of the
-// image is locked and needs to be flushed/invalidated.
-//
-// Emulated multi-plane buffers instead have a layout of:
-//
-// | Y | Y | Y | Y | Y | Y |
-// | Y | Y | Y | Y | Y | Y |
-// | Y | Y | Y | Y | Y | Y |
-// | Y | Y | Y | Y | Y | Y |
-// | Y | Y | Y | Y | Y | Y |
-// | Y | Y | Y | Y | Y | Y |
-// | U | U | U |   |   |   |
-// | U | U | U |   |   |   |
-// | U | U | U |   |   |   |
-// | V | V | V |   |   |   |
-// | V | V | V |   |   |   |
-// | V | V | V |   |   |   |
-//
-// where each plane is placed as a sub-image (albeit with a very large stride) in order to
-// simplify transfers into 3 sub-image transfers for the above example.
-//
-// Additional note: the V-plane is not placed to the right of the U-plane due to some
-// observed failures in media framework code which assumes the V-plane is not
-// "row-interlaced" with the U-plane.
-static void virgl_get_emulated_metadata(const struct bo *bo, struct bo_metadata *metadata)
-{
-	uint32_t y_plane_height;
-	uint32_t c_plane_height;
-	uint32_t original_width = bo->meta.width;
-	uint32_t original_height = bo->meta.height;
-
-	metadata->format = DRM_FORMAT_R8;
-	switch (bo->meta.format) {
-	case DRM_FORMAT_NV12:
-	case DRM_FORMAT_NV21:
-		// Bi-planar
-		metadata->num_planes = 2;
-
-		y_plane_height = original_height;
-		c_plane_height = DIV_ROUND_UP(original_height, 2);
-
-		metadata->width = original_width;
-		metadata->height = y_plane_height + c_plane_height;
-
-		// Y-plane (full resolution)
-		metadata->strides[0] = metadata->width;
-		metadata->offsets[0] = 0;
-		metadata->sizes[0] = metadata->width * y_plane_height;
-
-		// CbCr-plane  (half resolution, interleaved, placed below Y-plane)
-		metadata->strides[1] = metadata->width;
-		metadata->offsets[1] = metadata->offsets[0] + metadata->sizes[0];
-		metadata->sizes[1] = metadata->width * c_plane_height;
-
-		metadata->total_size = metadata->width * metadata->height;
-		break;
-	case DRM_FORMAT_YVU420:
-	case DRM_FORMAT_YVU420_ANDROID:
-		// Tri-planar
-		metadata->num_planes = 3;
-
-		y_plane_height = original_height;
-		c_plane_height = DIV_ROUND_UP(original_height, 2);
-
-		metadata->width = ALIGN(original_width, 32);
-		metadata->height = y_plane_height + (2 * c_plane_height);
-
-		// Y-plane (full resolution)
-		metadata->strides[0] = metadata->width;
-		metadata->offsets[0] = 0;
-		metadata->sizes[0] = metadata->width * original_height;
-
-		// Cb-plane (half resolution, placed below Y-plane)
-		metadata->strides[1] = metadata->width;
-		metadata->offsets[1] = metadata->offsets[0] + metadata->sizes[0];
-		metadata->sizes[1] = metadata->width * c_plane_height;
-
-		// Cr-plane (half resolution, placed below Cb-plane)
-		metadata->strides[2] = metadata->width;
-		metadata->offsets[2] = metadata->offsets[1] + metadata->sizes[1];
-		metadata->sizes[2] = metadata->width * c_plane_height;
-
-		metadata->total_size = metadata->width * metadata->height;
-		break;
-	default:
-		break;
-	}
-}
-
-struct virtio_transfers_params {
-	size_t xfers_needed;
-	struct rectangle xfer_boxes[DRV_MAX_PLANES];
-};
-
-static void virgl_get_emulated_transfers_params(const struct bo *bo,
-						const struct rectangle *transfer_box,
-						struct virtio_transfers_params *xfer_params)
-{
-	uint32_t y_plane_height;
-	uint32_t c_plane_height;
-	struct bo_metadata emulated_metadata;
-
-	if (transfer_box->x == 0 && transfer_box->y == 0 && transfer_box->width == bo->meta.width &&
-	    transfer_box->height == bo->meta.height) {
-		virgl_get_emulated_metadata(bo, &emulated_metadata);
-
-		xfer_params->xfers_needed = 1;
-		xfer_params->xfer_boxes[0].x = 0;
-		xfer_params->xfer_boxes[0].y = 0;
-		xfer_params->xfer_boxes[0].width = emulated_metadata.width;
-		xfer_params->xfer_boxes[0].height = emulated_metadata.height;
-
-		return;
-	}
-
-	switch (bo->meta.format) {
-	case DRM_FORMAT_NV12:
-	case DRM_FORMAT_NV21:
-		// Bi-planar
-		xfer_params->xfers_needed = 2;
-
-		y_plane_height = bo->meta.height;
-		c_plane_height = DIV_ROUND_UP(bo->meta.height, 2);
-
-		// Y-plane (full resolution)
-		xfer_params->xfer_boxes[0].x = transfer_box->x;
-		xfer_params->xfer_boxes[0].y = transfer_box->y;
-		xfer_params->xfer_boxes[0].width = transfer_box->width;
-		xfer_params->xfer_boxes[0].height = transfer_box->height;
-
-		// CbCr-plane (half resolution, interleaved, placed below Y-plane)
-		xfer_params->xfer_boxes[1].x = transfer_box->x;
-		xfer_params->xfer_boxes[1].y = transfer_box->y + y_plane_height;
-		xfer_params->xfer_boxes[1].width = transfer_box->width;
-		xfer_params->xfer_boxes[1].height = DIV_ROUND_UP(transfer_box->height, 2);
-
-		break;
-	case DRM_FORMAT_YVU420:
-	case DRM_FORMAT_YVU420_ANDROID:
-		// Tri-planar
-		xfer_params->xfers_needed = 3;
-
-		y_plane_height = bo->meta.height;
-		c_plane_height = DIV_ROUND_UP(bo->meta.height, 2);
-
-		// Y-plane (full resolution)
-		xfer_params->xfer_boxes[0].x = transfer_box->x;
-		xfer_params->xfer_boxes[0].y = transfer_box->y;
-		xfer_params->xfer_boxes[0].width = transfer_box->width;
-		xfer_params->xfer_boxes[0].height = transfer_box->height;
-
-		// Cb-plane (half resolution, placed below Y-plane)
-		xfer_params->xfer_boxes[1].x = transfer_box->x;
-		xfer_params->xfer_boxes[1].y = transfer_box->y + y_plane_height;
-		xfer_params->xfer_boxes[1].width = DIV_ROUND_UP(transfer_box->width, 2);
-		xfer_params->xfer_boxes[1].height = DIV_ROUND_UP(transfer_box->height, 2);
-
-		// Cr-plane (half resolution, placed below Cb-plane)
-		xfer_params->xfer_boxes[2].x = transfer_box->x;
-		xfer_params->xfer_boxes[2].y = transfer_box->y + y_plane_height + c_plane_height;
-		xfer_params->xfer_boxes[2].width = DIV_ROUND_UP(transfer_box->width, 2);
-		xfer_params->xfer_boxes[2].height = DIV_ROUND_UP(transfer_box->height, 2);
-
-		break;
-	}
-}
-
-static bool virgl_supports_combination_natively(struct driver *drv, uint32_t drm_format,
-						uint64_t use_flags)
-{
-	struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
-
-	if (priv->caps.max_version == 0)
-		return true;
-
-	if ((use_flags & BO_USE_RENDERING) &&
-	    !virgl_bitmask_supports_format(&priv->caps.v1.render, drm_format))
-		return false;
-
-	if ((use_flags & BO_USE_TEXTURE) &&
-	    !virgl_bitmask_supports_format(&priv->caps.v1.sampler, drm_format))
-		return false;
-
-	if ((use_flags & BO_USE_SCANOUT) && priv->caps_is_v2 &&
-	    !virgl_bitmask_supports_format(&priv->caps.v2.scanout, drm_format))
-		return false;
-
-	return true;
-}
-
-// For virtio backends that do not support formats natively (e.g. multi-planar formats are not
-// supported in virglrenderer when gbm is unavailable on the host machine), whether or not the
-// format and usage combination can be handled as a blob (byte buffer).
-static bool virgl_supports_combination_through_emulation(struct driver *drv, uint32_t drm_format,
-							 uint64_t use_flags)
-{
-	struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
-
-	// Only enable emulation on non-gbm virtio backends.
-	if (priv->host_gbm_enabled)
-		return false;
-
-	if (use_flags & (BO_USE_RENDERING | BO_USE_SCANOUT))
-		return false;
-
-	if (!virgl_supports_combination_natively(drv, DRM_FORMAT_R8, use_flags))
-		return false;
-
-	return drm_format == DRM_FORMAT_NV12 || drm_format == DRM_FORMAT_NV21 ||
-	       drm_format == DRM_FORMAT_YVU420 || drm_format == DRM_FORMAT_YVU420_ANDROID;
-}
-
-// Adds the given buffer combination to the list of supported buffer combinations if the
-// combination is supported by the virtio backend.
-static void virgl_add_combination(struct driver *drv, uint32_t drm_format,
-				  struct format_metadata *metadata, uint64_t use_flags)
-{
-	struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
-
-	if (params[param_3d].value && priv->caps.max_version >= 1) {
-		if ((use_flags & BO_USE_SCANOUT) && priv->caps_is_v2 &&
-		    !virgl_supports_combination_natively(drv, drm_format, use_flags)) {
-			drv_log("Scanout format: %d\n", drm_format);
-			use_flags &= ~BO_USE_SCANOUT;
-		}
-
-		if (!virgl_supports_combination_natively(drv, drm_format, use_flags) &&
-		    !virgl_supports_combination_through_emulation(drv, drm_format, use_flags)) {
-			drv_log("Skipping unsupported combination format:%d\n", drm_format);
-			return;
-		}
-	}
-
-	drv_add_combination(drv, drm_format, metadata, use_flags);
-}
-
-// Adds each given buffer combination to the list of supported buffer combinations if the
-// combination supported by the virtio backend.
-static void virgl_add_combinations(struct driver *drv, const uint32_t *drm_formats,
-				   uint32_t num_formats, struct format_metadata *metadata,
-				   uint64_t use_flags)
-{
-	uint32_t i;
-
-	for (i = 0; i < num_formats; i++)
-		virgl_add_combination(drv, drm_formats[i], metadata, use_flags);
-}
-
-static int virtio_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
-				 uint64_t use_flags)
-{
-	if (bo->meta.format != DRM_FORMAT_R8) {
-		width = ALIGN(width, MESA_LLVMPIPE_TILE_SIZE);
-		height = ALIGN(height, MESA_LLVMPIPE_TILE_SIZE);
-	}
-
-	return drv_dumb_bo_create_ex(bo, width, height, format, use_flags, BO_QUIRK_DUMB32BPP);
-}
-
-static inline void handle_flag(uint64_t *flag, uint64_t check_flag, uint32_t *bind,
-			       uint32_t virgl_bind)
-{
-	if ((*flag) & check_flag) {
-		(*flag) &= ~check_flag;
-		(*bind) |= virgl_bind;
-	}
-}
-
-static uint32_t compute_virgl_bind_flags(uint64_t use_flags, uint32_t format)
-{
-	/* In crosvm, VIRGL_BIND_SHARED means minigbm will allocate, not virglrenderer. */
-	uint32_t bind = VIRGL_BIND_SHARED;
-
-	handle_flag(&use_flags, BO_USE_TEXTURE, &bind, VIRGL_BIND_SAMPLER_VIEW);
-	handle_flag(&use_flags, BO_USE_RENDERING, &bind, VIRGL_BIND_RENDER_TARGET);
-	handle_flag(&use_flags, BO_USE_SCANOUT, &bind, VIRGL_BIND_SCANOUT);
-	handle_flag(&use_flags, BO_USE_CURSOR, &bind, VIRGL_BIND_CURSOR);
-	handle_flag(&use_flags, BO_USE_LINEAR, &bind, VIRGL_BIND_LINEAR);
-
-	if (use_flags & BO_USE_PROTECTED) {
-		handle_flag(&use_flags, BO_USE_PROTECTED, &bind, VIRGL_BIND_MINIGBM_PROTECTED);
-	} else {
-		// Make sure we don't set both flags, since that could be mistaken for
-		// protected. Give OFTEN priority over RARELY.
-		if (use_flags & BO_USE_SW_READ_OFTEN) {
-			handle_flag(&use_flags, BO_USE_SW_READ_OFTEN, &bind,
-				    VIRGL_BIND_MINIGBM_SW_READ_OFTEN);
-		} else {
-			handle_flag(&use_flags, BO_USE_SW_READ_RARELY, &bind,
-				    VIRGL_BIND_MINIGBM_SW_READ_RARELY);
-		}
-		if (use_flags & BO_USE_SW_WRITE_OFTEN) {
-			handle_flag(&use_flags, BO_USE_SW_WRITE_OFTEN, &bind,
-				    VIRGL_BIND_MINIGBM_SW_WRITE_OFTEN);
-		} else {
-			handle_flag(&use_flags, BO_USE_SW_WRITE_RARELY, &bind,
-				    VIRGL_BIND_MINIGBM_SW_WRITE_RARELY);
-		}
-	}
-
-	handle_flag(&use_flags, BO_USE_CAMERA_WRITE, &bind, VIRGL_BIND_MINIGBM_CAMERA_WRITE);
-	handle_flag(&use_flags, BO_USE_CAMERA_READ, &bind, VIRGL_BIND_MINIGBM_CAMERA_READ);
-	handle_flag(&use_flags, BO_USE_HW_VIDEO_DECODER, &bind,
-		    VIRGL_BIND_MINIGBM_HW_VIDEO_DECODER);
-	handle_flag(&use_flags, BO_USE_HW_VIDEO_ENCODER, &bind,
-		    VIRGL_BIND_MINIGBM_HW_VIDEO_ENCODER);
-
-	/*
-	 * HACK: This is for HAL_PIXEL_FORMAT_YV12 buffers allocated by arcvm. None of
-	 * our platforms can display YV12, so we can treat as a SW buffer. Remove once
-	 * this can be intelligently resolved in the guest. Also see gbm_bo_create.
-	 */
-	if (format == DRM_FORMAT_YVU420_ANDROID)
-		bind |= VIRGL_BIND_LINEAR;
-
-	if (use_flags)
-		drv_log("Unhandled bo use flag: %llx\n", (unsigned long long)use_flags);
-
-	return bind;
-}
-
-static int virgl_3d_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
-			      uint64_t use_flags)
-{
-	int ret;
-	size_t i;
-	uint32_t stride;
-	struct drm_virtgpu_resource_create res_create = { 0 };
-	struct bo_metadata emulated_metadata;
-
-	if (virgl_supports_combination_natively(bo->drv, format, use_flags)) {
-		stride = drv_stride_from_format(format, width, 0);
-		drv_bo_from_format(bo, stride, height, format);
-	} else {
-		assert(virgl_supports_combination_through_emulation(bo->drv, format, use_flags));
-
-		virgl_get_emulated_metadata(bo, &emulated_metadata);
-
-		format = emulated_metadata.format;
-		width = emulated_metadata.width;
-		height = emulated_metadata.height;
-		for (i = 0; i < emulated_metadata.num_planes; i++) {
-			bo->meta.strides[i] = emulated_metadata.strides[i];
-			bo->meta.offsets[i] = emulated_metadata.offsets[i];
-			bo->meta.sizes[i] = emulated_metadata.sizes[i];
-		}
-		bo->meta.total_size = emulated_metadata.total_size;
-	}
-
-	/*
-	 * Setting the target is intended to ensure this resource gets bound as a 2D
-	 * texture in the host renderer's GL state. All of these resource properties are
-	 * sent unchanged by the kernel to the host, which in turn sends them unchanged to
-	 * virglrenderer. When virglrenderer makes a resource, it will convert the target
-	 * enum to the equivalent one in GL and then bind the resource to that target.
-	 */
-
-	res_create.target = PIPE_TEXTURE_2D;
-	res_create.format = translate_format(format);
-	res_create.bind = compute_virgl_bind_flags(use_flags, format);
-	res_create.width = width;
-	res_create.height = height;
-
-	/* For virgl 3D */
-	res_create.depth = 1;
-	res_create.array_size = 1;
-	res_create.last_level = 0;
-	res_create.nr_samples = 0;
-
-	res_create.size = ALIGN(bo->meta.total_size, PAGE_SIZE); // PAGE_SIZE = 0x1000
-	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE, &res_create);
-	if (ret) {
-		drv_log("DRM_IOCTL_VIRTGPU_RESOURCE_CREATE failed with %s\n", strerror(errno));
-		return ret;
-	}
-
-	for (uint32_t plane = 0; plane < bo->meta.num_planes; plane++)
-		bo->handles[plane].u32 = res_create.bo_handle;
-
-	return 0;
-}
-
-static void *virgl_3d_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
-{
-	int ret;
-	struct drm_virtgpu_map gem_map = { 0 };
-
-	gem_map.handle = bo->handles[0].u32;
-	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_MAP, &gem_map);
-	if (ret) {
-		drv_log("DRM_IOCTL_VIRTGPU_MAP failed with %s\n", strerror(errno));
-		return MAP_FAILED;
-	}
-
-	vma->length = bo->meta.total_size;
-	return mmap(0, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd,
-		    gem_map.offset);
-}
-
-static int virgl_get_caps(struct driver *drv, union virgl_caps *caps, int *caps_is_v2)
-{
-	int ret;
-	struct drm_virtgpu_get_caps cap_args = { 0 };
-
-	*caps_is_v2 = 0;
-	cap_args.addr = (unsigned long long)caps;
-	if (params[param_capset_fix].value) {
-		*caps_is_v2 = 1;
-		cap_args.cap_set_id = 2;
-		cap_args.size = sizeof(union virgl_caps);
-	} else {
-		cap_args.cap_set_id = 1;
-		cap_args.size = sizeof(struct virgl_caps_v1);
-	}
-
-	ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GET_CAPS, &cap_args);
-	if (ret) {
-		drv_log("DRM_IOCTL_VIRTGPU_GET_CAPS failed with %s\n", strerror(errno));
-		*caps_is_v2 = 0;
-
-		// Fallback to v1
-		cap_args.cap_set_id = 1;
-		cap_args.size = sizeof(struct virgl_caps_v1);
-
-		ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GET_CAPS, &cap_args);
-		if (ret)
-			drv_log("DRM_IOCTL_VIRTGPU_GET_CAPS failed with %s\n", strerror(errno));
-	}
-
-	return ret;
-}
-
-static void virgl_init_params_and_caps(struct driver *drv)
-{
-	struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
-	if (params[param_3d].value) {
-		virgl_get_caps(drv, &priv->caps, &priv->caps_is_v2);
-
-		// We use two criteria to determine whether host minigbm is used on the host for
-		// swapchain allocations.
-		//
-		// (1) Host minigbm is only available via virglrenderer, and only virglrenderer
-		//     advertises capabilities.
-		// (2) Only host minigbm doesn't emulate YUV formats.  Checking this is a bit of a
-		//     proxy, but it works.
-		priv->host_gbm_enabled =
-		    priv->caps.max_version > 0 &&
-		    virgl_supports_combination_natively(drv, DRM_FORMAT_NV12, BO_USE_TEXTURE);
-	}
-}
-
-static int virgl_init(struct driver *drv)
-{
-	struct virgl_priv *priv;
-
-	priv = calloc(1, sizeof(*priv));
-	drv->priv = priv;
-
-	virgl_init_params_and_caps(drv);
-
-	if (params[param_3d].value) {
-		/* This doesn't mean host can scanout everything, it just means host
-		 * hypervisor can show it. */
-		virgl_add_combinations(drv, render_target_formats,
-				       ARRAY_SIZE(render_target_formats), &LINEAR_METADATA,
-				       BO_USE_RENDER_MASK | BO_USE_SCANOUT);
-		virgl_add_combinations(drv, texture_source_formats,
-				       ARRAY_SIZE(texture_source_formats), &LINEAR_METADATA,
-				       BO_USE_TEXTURE_MASK);
-	} else {
-		/* Virtio primary plane only allows this format. */
-		virgl_add_combination(drv, DRM_FORMAT_XRGB8888, &LINEAR_METADATA,
-				      BO_USE_RENDER_MASK | BO_USE_SCANOUT);
-		/* Virtio cursor plane only allows this format and Chrome cannot live without
-		 * ARGB888 renderable format. */
-		virgl_add_combination(drv, DRM_FORMAT_ARGB8888, &LINEAR_METADATA,
-				      BO_USE_RENDER_MASK | BO_USE_CURSOR);
-		/* Android needs more, but they cannot be bound as scanouts anymore after
-		 * "drm/virtio: fix DRM_FORMAT_* handling" */
-		virgl_add_combinations(drv, render_target_formats,
-				       ARRAY_SIZE(render_target_formats), &LINEAR_METADATA,
-				       BO_USE_RENDER_MASK);
-		virgl_add_combinations(drv, dumb_texture_source_formats,
-				       ARRAY_SIZE(dumb_texture_source_formats), &LINEAR_METADATA,
-				       BO_USE_TEXTURE_MASK);
-		virgl_add_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA,
-				      BO_USE_SW_MASK | BO_USE_LINEAR);
-		virgl_add_combination(drv, DRM_FORMAT_NV21, &LINEAR_METADATA,
-				      BO_USE_SW_MASK | BO_USE_LINEAR);
-	}
-
-	/* Android CTS tests require this. */
-	virgl_add_combination(drv, DRM_FORMAT_RGB888, &LINEAR_METADATA, BO_USE_SW_MASK);
-	virgl_add_combination(drv, DRM_FORMAT_BGR888, &LINEAR_METADATA, BO_USE_SW_MASK);
-	virgl_add_combination(drv, DRM_FORMAT_ABGR16161616F, &LINEAR_METADATA,
-				   BO_USE_SW_MASK | BO_USE_TEXTURE_MASK);
-	virgl_add_combination(drv, DRM_FORMAT_ABGR2101010, &LINEAR_METADATA,
-			      BO_USE_SW_MASK | BO_USE_TEXTURE_MASK);
-	virgl_add_combination(drv, DRM_FORMAT_P010, &LINEAR_METADATA,
-				   BO_USE_SW_MASK | BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
-
-	drv_modify_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA,
-			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER |
-				   BO_USE_HW_VIDEO_ENCODER);
-	drv_modify_combination(drv, DRM_FORMAT_R8, &LINEAR_METADATA,
-			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER |
-				   BO_USE_HW_VIDEO_ENCODER);
-
-	if (!priv->host_gbm_enabled) {
-		drv_modify_combination(drv, DRM_FORMAT_ABGR8888, &LINEAR_METADATA,
-				       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE |
-					   BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER);
-		drv_modify_combination(drv, DRM_FORMAT_XBGR8888, &LINEAR_METADATA,
-				       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE |
-					   BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER);
-		drv_modify_combination(drv, DRM_FORMAT_NV21, &LINEAR_METADATA,
-				       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE |
-					   BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER);
-		drv_modify_combination(drv, DRM_FORMAT_R16, &LINEAR_METADATA,
-				       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE |
-					   BO_USE_HW_VIDEO_DECODER);
-		drv_modify_combination(drv, DRM_FORMAT_YVU420, &LINEAR_METADATA,
-				       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE |
-					   BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER);
-		drv_modify_combination(drv, DRM_FORMAT_YVU420_ANDROID, &LINEAR_METADATA,
-				       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE |
-					   BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER);
-	}
-
-	return drv_modify_linear_combinations(drv);
-}
-
-static void virgl_close(struct driver *drv)
-{
-	free(drv->priv);
-	drv->priv = NULL;
-}
-
-static int virgl_bo_create_blob(struct driver *drv, struct bo *bo)
-{
-	int ret;
-	uint32_t stride;
-	uint32_t cur_blob_id;
-	uint32_t cmd[VIRGL_PIPE_RES_CREATE_SIZE + 1] = { 0 };
-	struct drm_virtgpu_resource_create_blob drm_rc_blob = { 0 };
-	struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
-
-	uint32_t blob_flags = VIRTGPU_BLOB_FLAG_USE_SHAREABLE;
-	if (bo->meta.use_flags & BO_USE_SW_MASK)
-		blob_flags |= VIRTGPU_BLOB_FLAG_USE_MAPPABLE;
-	if (bo->meta.use_flags & BO_USE_NON_GPU_HW)
-		blob_flags |= VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE;
-
-	cur_blob_id = atomic_fetch_add(&priv->next_blob_id, 1);
-	stride = drv_stride_from_format(bo->meta.format, bo->meta.width, 0);
-	drv_bo_from_format(bo, stride, bo->meta.height, bo->meta.format);
-	bo->meta.total_size = ALIGN(bo->meta.total_size, PAGE_SIZE);
-	bo->meta.tiling = blob_flags;
-
-	cmd[0] = VIRGL_CMD0(VIRGL_CCMD_PIPE_RESOURCE_CREATE, 0, VIRGL_PIPE_RES_CREATE_SIZE);
-	cmd[VIRGL_PIPE_RES_CREATE_TARGET] = PIPE_TEXTURE_2D;
-	cmd[VIRGL_PIPE_RES_CREATE_WIDTH] = bo->meta.width;
-	cmd[VIRGL_PIPE_RES_CREATE_HEIGHT] = bo->meta.height;
-	cmd[VIRGL_PIPE_RES_CREATE_FORMAT] = translate_format(bo->meta.format);
-	cmd[VIRGL_PIPE_RES_CREATE_BIND] =
-	    compute_virgl_bind_flags(bo->meta.use_flags, bo->meta.format);
-	cmd[VIRGL_PIPE_RES_CREATE_DEPTH] = 1;
-	cmd[VIRGL_PIPE_RES_CREATE_BLOB_ID] = cur_blob_id;
-
-	drm_rc_blob.cmd = (uint64_t)&cmd;
-	drm_rc_blob.cmd_size = 4 * (VIRGL_PIPE_RES_CREATE_SIZE + 1);
-	drm_rc_blob.size = bo->meta.total_size;
-	drm_rc_blob.blob_mem = VIRTGPU_BLOB_MEM_HOST3D;
-	drm_rc_blob.blob_flags = blob_flags;
-	drm_rc_blob.blob_id = cur_blob_id;
-
-	ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB, &drm_rc_blob);
-	if (ret < 0) {
-		drv_log("DRM_VIRTGPU_RESOURCE_CREATE_BLOB failed with %s\n", strerror(errno));
-		return -errno;
-	}
-
-	for (uint32_t plane = 0; plane < bo->meta.num_planes; plane++)
-		bo->handles[plane].u32 = drm_rc_blob.bo_handle;
-
-	return 0;
-}
-
-static bool should_use_blob(struct driver *drv, uint32_t format, uint64_t use_flags)
-{
-	struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
-
-	// TODO(gurchetansingh): remove once all minigbm users are blob-safe
-#ifndef VIRTIO_GPU_NEXT
-	return false;
-#endif
-
-	// Only use blob when host gbm is available
-	if (!priv->host_gbm_enabled)
-		return false;
-
-	// Use regular resources if only the GPU needs efficient access
-	if (!(use_flags &
-	      (BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN | BO_USE_LINEAR | BO_USE_NON_GPU_HW)))
-		return false;
-
-	switch (format) {
-	case DRM_FORMAT_YVU420_ANDROID:
-	case DRM_FORMAT_R8:
-		// Formats with strictly defined strides are supported
-		return true;
-	case DRM_FORMAT_NV12:
-		// Knowing buffer metadata at buffer creation isn't yet supported, so buffers
-		// can't be properly mapped into the guest.
-		return (use_flags & BO_USE_SW_MASK) == 0;
-	default:
-		return false;
-	}
-}
-
-static int virgl_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
-			   uint64_t use_flags)
-{
-	if (params[param_resource_blob].value && params[param_host_visible].value &&
-	    should_use_blob(bo->drv, format, use_flags))
-		return virgl_bo_create_blob(bo->drv, bo);
-
-	if (params[param_3d].value)
-		return virgl_3d_bo_create(bo, width, height, format, use_flags);
-	else
-		return virtio_dumb_bo_create(bo, width, height, format, use_flags);
-}
-
-static int virgl_bo_destroy(struct bo *bo)
-{
-	if (params[param_3d].value)
-		return drv_gem_bo_destroy(bo);
-	else
-		return drv_dumb_bo_destroy(bo);
-}
-
-static void *virgl_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
-{
-	if (params[param_3d].value)
-		return virgl_3d_bo_map(bo, vma, plane, map_flags);
-	else
-		return drv_dumb_bo_map(bo, vma, plane, map_flags);
-}
-
-static int virgl_bo_invalidate(struct bo *bo, struct mapping *mapping)
-{
-	int ret;
-	size_t i;
-	struct drm_virtgpu_3d_transfer_from_host xfer = { 0 };
-	struct drm_virtgpu_3d_wait waitcmd = { 0 };
-	struct virtio_transfers_params xfer_params;
-	struct virgl_priv *priv = (struct virgl_priv *)bo->drv->priv;
-	uint64_t host_write_flags;
-
-	if (!params[param_3d].value)
-		return 0;
-
-	// Invalidate is only necessary if the host writes to the buffer. The encoder and
-	// decoder flags don't differentiate between input and output buffers, but we can
-	// use the format to determine whether this buffer could be encoder/decoder output.
-	host_write_flags = BO_USE_RENDERING | BO_USE_CAMERA_WRITE;
-	if (bo->meta.format == DRM_FORMAT_R8)
-		host_write_flags |= BO_USE_HW_VIDEO_ENCODER;
-	else
-		host_write_flags |= BO_USE_HW_VIDEO_DECODER;
-
-	if ((bo->meta.use_flags & host_write_flags) == 0)
-		return 0;
-
-	if (params[param_resource_blob].value && (bo->meta.tiling & VIRTGPU_BLOB_FLAG_USE_MAPPABLE))
-		return 0;
-
-	xfer.bo_handle = mapping->vma->handle;
-
-	if (mapping->rect.x || mapping->rect.y) {
-		/*
-		 * virglrenderer uses the box parameters and assumes that offset == 0 for planar
-		 * images
-		 */
-		if (bo->meta.num_planes == 1) {
-			xfer.offset =
-			    (bo->meta.strides[0] * mapping->rect.y) +
-			    drv_bytes_per_pixel_from_format(bo->meta.format, 0) * mapping->rect.x;
-		}
-	}
-
-	if ((bo->meta.use_flags & BO_USE_RENDERING) == 0) {
-		// Unfortunately, the kernel doesn't actually pass the guest layer_stride
-		// and guest stride to the host (compare virgl.h and virtgpu_drm.h).
-		// For gbm based resources, we can work around this by using the level field
-		// to pass the stride to virglrenderer's gbm transfer code. However, we need
-		// to avoid doing this for resources which don't rely on that transfer code,
-		// which is resources with the BO_USE_RENDERING flag set.
-		// TODO(b/145993887): Send also stride when the patches are landed
-		if (priv->host_gbm_enabled)
-			xfer.level = bo->meta.strides[0];
-	}
-
-	if (virgl_supports_combination_natively(bo->drv, bo->meta.format, bo->meta.use_flags)) {
-		xfer_params.xfers_needed = 1;
-		xfer_params.xfer_boxes[0] = mapping->rect;
-	} else {
-		assert(virgl_supports_combination_through_emulation(bo->drv, bo->meta.format,
-								    bo->meta.use_flags));
-
-		virgl_get_emulated_transfers_params(bo, &mapping->rect, &xfer_params);
-	}
-
-	for (i = 0; i < xfer_params.xfers_needed; i++) {
-		xfer.box.x = xfer_params.xfer_boxes[i].x;
-		xfer.box.y = xfer_params.xfer_boxes[i].y;
-		xfer.box.w = xfer_params.xfer_boxes[i].width;
-		xfer.box.h = xfer_params.xfer_boxes[i].height;
-		xfer.box.d = 1;
-
-		ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST, &xfer);
-		if (ret) {
-			drv_log("DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST failed with %s\n",
-				strerror(errno));
-			return -errno;
-		}
-	}
-
-	// The transfer needs to complete before invalidate returns so that any host changes
-	// are visible and to ensure the host doesn't overwrite subsequent guest changes.
-	// TODO(b/136733358): Support returning fences from transfers
-	waitcmd.handle = mapping->vma->handle;
-	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_WAIT, &waitcmd);
-	if (ret) {
-		drv_log("DRM_IOCTL_VIRTGPU_WAIT failed with %s\n", strerror(errno));
-		return -errno;
-	}
-
-	return 0;
-}
-
-static int virgl_bo_flush(struct bo *bo, struct mapping *mapping)
-{
-	int ret;
-	size_t i;
-	struct drm_virtgpu_3d_transfer_to_host xfer = { 0 };
-	struct drm_virtgpu_3d_wait waitcmd = { 0 };
-	struct virtio_transfers_params xfer_params;
-	struct virgl_priv *priv = (struct virgl_priv *)bo->drv->priv;
-
-	if (!params[param_3d].value)
-		return 0;
-
-	if (!(mapping->vma->map_flags & BO_MAP_WRITE))
-		return 0;
-
-	if (params[param_resource_blob].value && (bo->meta.tiling & VIRTGPU_BLOB_FLAG_USE_MAPPABLE))
-		return 0;
-
-	xfer.bo_handle = mapping->vma->handle;
-
-	if (mapping->rect.x || mapping->rect.y) {
-		/*
-		 * virglrenderer uses the box parameters and assumes that offset == 0 for planar
-		 * images
-		 */
-		if (bo->meta.num_planes == 1) {
-			xfer.offset =
-			    (bo->meta.strides[0] * mapping->rect.y) +
-			    drv_bytes_per_pixel_from_format(bo->meta.format, 0) * mapping->rect.x;
-		}
-	}
-
-	// Unfortunately, the kernel doesn't actually pass the guest layer_stride and
-	// guest stride to the host (compare virgl.h and virtgpu_drm.h). We can use
-	// the level to work around this.
-	if (priv->host_gbm_enabled)
-		xfer.level = bo->meta.strides[0];
-
-	if (virgl_supports_combination_natively(bo->drv, bo->meta.format, bo->meta.use_flags)) {
-		xfer_params.xfers_needed = 1;
-		xfer_params.xfer_boxes[0] = mapping->rect;
-	} else {
-		assert(virgl_supports_combination_through_emulation(bo->drv, bo->meta.format,
-								    bo->meta.use_flags));
-
-		virgl_get_emulated_transfers_params(bo, &mapping->rect, &xfer_params);
-	}
-
-	for (i = 0; i < xfer_params.xfers_needed; i++) {
-		xfer.box.x = xfer_params.xfer_boxes[i].x;
-		xfer.box.y = xfer_params.xfer_boxes[i].y;
-		xfer.box.w = xfer_params.xfer_boxes[i].width;
-		xfer.box.h = xfer_params.xfer_boxes[i].height;
-		xfer.box.d = 1;
-
-		ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST, &xfer);
-		if (ret) {
-			drv_log("DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST failed with %s\n",
-				strerror(errno));
-			return -errno;
-		}
-	}
-
-	// If the buffer is only accessed by the host GPU, then the flush is ordered
-	// with subsequent commands. However, if other host hardware can access the
-	// buffer, we need to wait for the transfer to complete for consistency.
-	// TODO(b/136733358): Support returning fences from transfers
-	if (bo->meta.use_flags & BO_USE_NON_GPU_HW) {
-		waitcmd.handle = mapping->vma->handle;
-
-		ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_WAIT, &waitcmd);
-		if (ret) {
-			drv_log("DRM_IOCTL_VIRTGPU_WAIT failed with %s\n", strerror(errno));
-			return -errno;
-		}
-	}
-
-	return 0;
-}
-
-static uint32_t virgl_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags)
-{
-	switch (format) {
-	case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
-		/* Camera subsystem requires NV12. */
-		if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE))
-			return DRM_FORMAT_NV12;
-		/*HACK: See b/28671744 */
-		return DRM_FORMAT_XBGR8888;
-	case DRM_FORMAT_FLEX_YCbCr_420_888:
-		/*
-		 * All of our host drivers prefer NV12 as their flexible media format.
-		 * If that changes, this will need to be modified.
-		 */
-		if (params[param_3d].value)
-			return DRM_FORMAT_NV12;
-		else
-			return DRM_FORMAT_YVU420_ANDROID;
-	default:
-		return format;
-	}
-}
-static int virgl_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES],
-			       uint32_t offsets[DRV_MAX_PLANES], uint64_t *format_modifier)
-{
-	int ret;
-	struct drm_virtgpu_resource_info_cros res_info = { 0 };
-
-	if (!params[param_3d].value)
-		return 0;
-
-	res_info.bo_handle = bo->handles[0].u32;
-	res_info.type = VIRTGPU_RESOURCE_INFO_TYPE_EXTENDED;
-	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_INFO_CROS, &res_info);
-	if (ret) {
-		drv_log("DRM_IOCTL_VIRTGPU_RESOURCE_INFO failed with %s\n", strerror(errno));
-		return ret;
-	}
-
-	for (uint32_t plane = 0; plane < bo->meta.num_planes; plane++) {
-		/*
-		 * Currently, kernel v4.14 (Betty) doesn't have the extended resource info
-		 * ioctl.
-		 */
-		if (res_info.strides[plane]) {
-			strides[plane] = res_info.strides[plane];
-			offsets[plane] = res_info.offsets[plane];
-		}
-	}
-	*format_modifier = res_info.format_modifier;
-
-	return 0;
-}
-
-const struct backend virtgpu_virgl = { .name = "virtgpu_virgl",
-				       .init = virgl_init,
-				       .close = virgl_close,
-				       .bo_create = virgl_bo_create,
-				       .bo_destroy = virgl_bo_destroy,
-				       .bo_import = drv_prime_bo_import,
-				       .bo_map = virgl_bo_map,
-				       .bo_unmap = drv_bo_munmap,
-				       .bo_invalidate = virgl_bo_invalidate,
-				       .bo_flush = virgl_bo_flush,
-				       .resolve_format = virgl_resolve_format,
-				       .resource_info = virgl_resource_info };
diff --git a/virtio_gpu.c b/virtio_gpu.c
new file mode 100644
index 0000000..ed67693
--- /dev/null
+++ b/virtio_gpu.c
@@ -0,0 +1,885 @@
+/*
+ * Copyright 2017 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <xf86drm.h>
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+#include "virgl_hw.h"
+#include "virtgpu_drm.h"
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE 0x1000
+#endif
+#define PIPE_TEXTURE_2D 2
+
+#define MESA_LLVMPIPE_TILE_ORDER 6
+#define MESA_LLVMPIPE_TILE_SIZE (1 << MESA_LLVMPIPE_TILE_ORDER)
+
+struct feature {
+	uint64_t feature;
+	const char *name;
+	uint32_t enabled;
+};
+
+enum feature_id {
+	feat_3d,
+	feat_capset_fix,
+	feat_max,
+};
+
+#define FEATURE(x)                                                                                 \
+	(struct feature)                                                                           \
+	{                                                                                          \
+		x, #x, 0                                                                           \
+	}
+
+static struct feature features[] = { FEATURE(VIRTGPU_PARAM_3D_FEATURES),
+				     FEATURE(VIRTGPU_PARAM_CAPSET_QUERY_FIX) };
+
+static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888,
+						  DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888,
+						  DRM_FORMAT_XRGB8888 };
+
+static const uint32_t dumb_texture_source_formats[] = {
+	DRM_FORMAT_R8,	 DRM_FORMAT_R16,  DRM_FORMAT_YVU420,
+	DRM_FORMAT_NV12, DRM_FORMAT_NV21, DRM_FORMAT_YVU420_ANDROID
+};
+
+static const uint32_t texture_source_formats[] = { DRM_FORMAT_NV12, DRM_FORMAT_NV21,
+						   DRM_FORMAT_R8,   DRM_FORMAT_R16,
+						   DRM_FORMAT_RG88, DRM_FORMAT_YVU420_ANDROID };
+
+struct virtio_gpu_priv {
+	int caps_is_v2;
+	union virgl_caps caps;
+	int host_gbm_enabled;
+};
+
+static uint32_t translate_format(uint32_t drm_fourcc)
+{
+	switch (drm_fourcc) {
+	case DRM_FORMAT_BGR888:
+	case DRM_FORMAT_RGB888:
+		return VIRGL_FORMAT_R8G8B8_UNORM;
+	case DRM_FORMAT_XRGB8888:
+		return VIRGL_FORMAT_B8G8R8X8_UNORM;
+	case DRM_FORMAT_ARGB8888:
+		return VIRGL_FORMAT_B8G8R8A8_UNORM;
+	case DRM_FORMAT_XBGR8888:
+		return VIRGL_FORMAT_R8G8B8X8_UNORM;
+	case DRM_FORMAT_ABGR8888:
+		return VIRGL_FORMAT_R8G8B8A8_UNORM;
+	case DRM_FORMAT_ABGR16161616F:
+		return VIRGL_FORMAT_R16G16B16A16_UNORM;
+	case DRM_FORMAT_RGB565:
+		return VIRGL_FORMAT_B5G6R5_UNORM;
+	case DRM_FORMAT_R8:
+		return VIRGL_FORMAT_R8_UNORM;
+	case DRM_FORMAT_RG88:
+		return VIRGL_FORMAT_R8G8_UNORM;
+	case DRM_FORMAT_NV12:
+		return VIRGL_FORMAT_NV12;
+	case DRM_FORMAT_NV21:
+		return VIRGL_FORMAT_NV21;
+	case DRM_FORMAT_YVU420:
+	case DRM_FORMAT_YVU420_ANDROID:
+		return VIRGL_FORMAT_YV12;
+	default:
+		return 0;
+	}
+}
+
+static bool virtio_gpu_bitmask_supports_format(struct virgl_supported_format_mask *supported,
+					       uint32_t drm_format)
+{
+	uint32_t virgl_format = translate_format(drm_format);
+	if (!virgl_format) {
+		return false;
+	}
+
+	uint32_t bitmask_index = virgl_format / 32;
+	uint32_t bit_index = virgl_format % 32;
+	return supported->bitmask[bitmask_index] & (1 << bit_index);
+}
+
+// The metadata generated here for emulated buffers is slightly different than the metadata
+// generated by drv_bo_from_format. In order to simplify transfers in the flush and invalidate
+// functions below, the emulated buffers are oversized. For example, ignoring stride alignment
+// requirements to demonstrate, a 6x6 YUV420 image buffer might have the following layout from
+// drv_bo_from_format:
+//
+// | Y | Y | Y | Y | Y | Y |
+// | Y | Y | Y | Y | Y | Y |
+// | Y | Y | Y | Y | Y | Y |
+// | Y | Y | Y | Y | Y | Y |
+// | Y | Y | Y | Y | Y | Y |
+// | Y | Y | Y | Y | Y | Y |
+// | U | U | U | U | U | U |
+// | U | U | U | V | V | V |
+// | V | V | V | V | V | V |
+//
+// where each plane immediately follows the previous plane in memory. This layout makes it
+// difficult to compute the transfers needed for example when the middle 2x2 region of the
+// image is locked and needs to be flushed/invalidated.
+//
+// Emulated multi-plane buffers instead have a layout of:
+//
+// | Y | Y | Y | Y | Y | Y |
+// | Y | Y | Y | Y | Y | Y |
+// | Y | Y | Y | Y | Y | Y |
+// | Y | Y | Y | Y | Y | Y |
+// | Y | Y | Y | Y | Y | Y |
+// | Y | Y | Y | Y | Y | Y |
+// | U | U | U |   |   |   |
+// | U | U | U |   |   |   |
+// | U | U | U |   |   |   |
+// | V | V | V |   |   |   |
+// | V | V | V |   |   |   |
+// | V | V | V |   |   |   |
+//
+// where each plane is placed as a sub-image (albeit with a very large stride) in order to
+// simplify transfers into 3 sub-image transfers for the above example.
+//
+// Additional note: the V-plane is not placed to the right of the U-plane due to some
+// observed failures in media framework code which assumes the V-plane is not
+// "row-interlaced" with the U-plane.
+static void virtio_gpu_get_emulated_metadata(const struct bo *bo, struct bo_metadata *metadata)
+{
+	uint32_t y_plane_height;
+	uint32_t c_plane_height;
+	uint32_t original_width = bo->meta.width;
+	uint32_t original_height = bo->meta.height;
+
+	metadata->format = DRM_FORMAT_R8;
+	switch (bo->meta.format) {
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV21:
+		// Bi-planar
+		metadata->num_planes = 2;
+
+		y_plane_height = original_height;
+		c_plane_height = DIV_ROUND_UP(original_height, 2);
+
+		metadata->width = original_width;
+		metadata->height = y_plane_height + c_plane_height;
+
+		// Y-plane (full resolution)
+		metadata->strides[0] = metadata->width;
+		metadata->offsets[0] = 0;
+		metadata->sizes[0] = metadata->width * y_plane_height;
+
+		// CbCr-plane  (half resolution, interleaved, placed below Y-plane)
+		metadata->strides[1] = metadata->width;
+		metadata->offsets[1] = metadata->offsets[0] + metadata->sizes[0];
+		metadata->sizes[1] = metadata->width * c_plane_height;
+
+		metadata->total_size = metadata->width * metadata->height;
+		break;
+	case DRM_FORMAT_YVU420:
+	case DRM_FORMAT_YVU420_ANDROID:
+		// Tri-planar
+		metadata->num_planes = 3;
+
+		y_plane_height = original_height;
+		c_plane_height = DIV_ROUND_UP(original_height, 2);
+
+		metadata->width = ALIGN(original_width, 32);
+		metadata->height = y_plane_height + (2 * c_plane_height);
+
+		// Y-plane (full resolution)
+		metadata->strides[0] = metadata->width;
+		metadata->offsets[0] = 0;
+		metadata->sizes[0] = metadata->width * original_height;
+
+		// Cb-plane (half resolution, placed below Y-plane)
+		metadata->strides[1] = metadata->width;
+		metadata->offsets[1] = metadata->offsets[0] + metadata->sizes[0];
+		metadata->sizes[1] = metadata->width * c_plane_height;
+
+		// Cr-plane (half resolution, placed below Cb-plane)
+		metadata->strides[2] = metadata->width;
+		metadata->offsets[2] = metadata->offsets[1] + metadata->sizes[1];
+		metadata->sizes[2] = metadata->width * c_plane_height;
+
+		metadata->total_size = metadata->width * metadata->height;
+		break;
+	default:
+		break;
+	}
+}
+
+struct virtio_transfers_params {
+	size_t xfers_needed;
+	struct rectangle xfer_boxes[DRV_MAX_PLANES];
+};
+
+static void virtio_gpu_get_emulated_transfers_params(const struct bo *bo,
+						     const struct rectangle *transfer_box,
+						     struct virtio_transfers_params *xfer_params)
+{
+	uint32_t y_plane_height;
+	uint32_t c_plane_height;
+	struct bo_metadata emulated_metadata;
+
+	if (transfer_box->x == 0 && transfer_box->y == 0 && transfer_box->width == bo->meta.width &&
+	    transfer_box->height == bo->meta.height) {
+		virtio_gpu_get_emulated_metadata(bo, &emulated_metadata);
+
+		xfer_params->xfers_needed = 1;
+		xfer_params->xfer_boxes[0].x = 0;
+		xfer_params->xfer_boxes[0].y = 0;
+		xfer_params->xfer_boxes[0].width = emulated_metadata.width;
+		xfer_params->xfer_boxes[0].height = emulated_metadata.height;
+
+		return;
+	}
+
+	switch (bo->meta.format) {
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV21:
+		// Bi-planar
+		xfer_params->xfers_needed = 2;
+
+		y_plane_height = bo->meta.height;
+		c_plane_height = DIV_ROUND_UP(bo->meta.height, 2);
+
+		// Y-plane (full resolution)
+		xfer_params->xfer_boxes[0].x = transfer_box->x;
+		xfer_params->xfer_boxes[0].y = transfer_box->y;
+		xfer_params->xfer_boxes[0].width = transfer_box->width;
+		xfer_params->xfer_boxes[0].height = transfer_box->height;
+
+		// CbCr-plane (half resolution, interleaved, placed below Y-plane)
+		xfer_params->xfer_boxes[1].x = transfer_box->x;
+		xfer_params->xfer_boxes[1].y = transfer_box->y + y_plane_height;
+		xfer_params->xfer_boxes[1].width = transfer_box->width;
+		xfer_params->xfer_boxes[1].height = DIV_ROUND_UP(transfer_box->height, 2);
+
+		break;
+	case DRM_FORMAT_YVU420:
+	case DRM_FORMAT_YVU420_ANDROID:
+		// Tri-planar
+		xfer_params->xfers_needed = 3;
+
+		y_plane_height = bo->meta.height;
+		c_plane_height = DIV_ROUND_UP(bo->meta.height, 2);
+
+		// Y-plane (full resolution)
+		xfer_params->xfer_boxes[0].x = transfer_box->x;
+		xfer_params->xfer_boxes[0].y = transfer_box->y;
+		xfer_params->xfer_boxes[0].width = transfer_box->width;
+		xfer_params->xfer_boxes[0].height = transfer_box->height;
+
+		// Cb-plane (half resolution, placed below Y-plane)
+		xfer_params->xfer_boxes[1].x = transfer_box->x;
+		xfer_params->xfer_boxes[1].y = transfer_box->y + y_plane_height;
+		xfer_params->xfer_boxes[1].width = DIV_ROUND_UP(transfer_box->width, 2);
+		xfer_params->xfer_boxes[1].height = DIV_ROUND_UP(transfer_box->height, 2);
+
+		// Cr-plane (half resolution, placed below Cb-plane)
+		xfer_params->xfer_boxes[2].x = transfer_box->x;
+		xfer_params->xfer_boxes[2].y = transfer_box->y + y_plane_height + c_plane_height;
+		xfer_params->xfer_boxes[2].width = DIV_ROUND_UP(transfer_box->width, 2);
+		xfer_params->xfer_boxes[2].height = DIV_ROUND_UP(transfer_box->height, 2);
+
+		break;
+	}
+}
+
+static bool virtio_gpu_supports_combination_natively(struct driver *drv, uint32_t drm_format,
+						     uint64_t use_flags)
+{
+	struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)drv->priv;
+
+	if (priv->caps.max_version == 0) {
+		return true;
+	}
+
+	if ((use_flags & BO_USE_RENDERING) &&
+	    !virtio_gpu_bitmask_supports_format(&priv->caps.v1.render, drm_format)) {
+		return false;
+	}
+
+	if ((use_flags & BO_USE_TEXTURE) &&
+	    !virtio_gpu_bitmask_supports_format(&priv->caps.v1.sampler, drm_format)) {
+		return false;
+	}
+
+	if ((use_flags & BO_USE_SCANOUT) && priv->caps_is_v2 &&
+	    !virtio_gpu_bitmask_supports_format(&priv->caps.v2.scanout, drm_format)) {
+		return false;
+	}
+
+	return true;
+}
+
+// For virtio backends that do not support formats natively (e.g. multi-planar formats are not
+// supported in virglrenderer when gbm is unavailable on the host machine), whether or not the
+// format and usage combination can be handled as a blob (byte buffer).
+static bool virtio_gpu_supports_combination_through_emulation(struct driver *drv,
+							      uint32_t drm_format,
+							      uint64_t use_flags)
+{
+	struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)drv->priv;
+
+	// Only enable emulation on non-gbm virtio backends.
+	if (priv->host_gbm_enabled) {
+		return false;
+	}
+
+	if (use_flags & (BO_USE_RENDERING | BO_USE_SCANOUT)) {
+		return false;
+	}
+
+	if (!virtio_gpu_supports_combination_natively(drv, DRM_FORMAT_R8, use_flags)) {
+		return false;
+	}
+
+	return drm_format == DRM_FORMAT_NV12 || drm_format == DRM_FORMAT_NV21 ||
+	       drm_format == DRM_FORMAT_YVU420 || drm_format == DRM_FORMAT_YVU420_ANDROID;
+}
+
+// Adds the given buffer combination to the list of supported buffer combinations if the
+// combination is supported by the virtio backend.
+static void virtio_gpu_add_combination(struct driver *drv, uint32_t drm_format,
+				       struct format_metadata *metadata, uint64_t use_flags)
+{
+	struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)drv->priv;
+
+	if (features[feat_3d].enabled && priv->caps.max_version >= 1) {
+		if ((use_flags & BO_USE_SCANOUT) && priv->caps_is_v2 &&
+		    !virtio_gpu_supports_combination_natively(drv, drm_format, use_flags)) {
+			drv_log("Scanout format: %d\n", drm_format);
+			use_flags &= ~BO_USE_SCANOUT;
+		}
+
+		if (!virtio_gpu_supports_combination_natively(drv, drm_format, use_flags) &&
+		    !virtio_gpu_supports_combination_through_emulation(drv, drm_format,
+								       use_flags)) {
+			drv_log("Skipping unsupported combination format:%d\n", drm_format);
+			return;
+		}
+	}
+
+	drv_add_combination(drv, drm_format, metadata, use_flags);
+}
+
+// Adds each given buffer combination to the list of supported buffer combinations if the
+// combination supported by the virtio backend.
+static void virtio_gpu_add_combinations(struct driver *drv, const uint32_t *drm_formats,
+					uint32_t num_formats, struct format_metadata *metadata,
+					uint64_t use_flags)
+{
+	uint32_t i;
+
+	for (i = 0; i < num_formats; i++) {
+		virtio_gpu_add_combination(drv, drm_formats[i], metadata, use_flags);
+	}
+}
+
+static int virtio_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+				 uint64_t use_flags)
+{
+	if (bo->meta.format != DRM_FORMAT_R8) {
+		width = ALIGN(width, MESA_LLVMPIPE_TILE_SIZE);
+		height = ALIGN(height, MESA_LLVMPIPE_TILE_SIZE);
+	}
+
+	return drv_dumb_bo_create_ex(bo, width, height, format, use_flags, BO_QUIRK_DUMB32BPP);
+}
+
+static inline void handle_flag(uint64_t *flag, uint64_t check_flag, uint32_t *bind,
+			       uint32_t virgl_bind)
+{
+	if ((*flag) & check_flag) {
+		(*flag) &= ~check_flag;
+		(*bind) |= virgl_bind;
+	}
+}
+
+static uint32_t use_flags_to_bind(uint64_t use_flags)
+{
+	/* In crosvm, VIRGL_BIND_SHARED means minigbm will allocate, not virglrenderer. */
+	uint32_t bind = VIRGL_BIND_SHARED;
+
+	handle_flag(&use_flags, BO_USE_TEXTURE, &bind, VIRGL_BIND_SAMPLER_VIEW);
+	handle_flag(&use_flags, BO_USE_RENDERING, &bind, VIRGL_BIND_RENDER_TARGET);
+	handle_flag(&use_flags, BO_USE_SCANOUT, &bind, VIRGL_BIND_SCANOUT);
+	handle_flag(&use_flags, BO_USE_CURSOR, &bind, VIRGL_BIND_CURSOR);
+	handle_flag(&use_flags, BO_USE_LINEAR, &bind, VIRGL_BIND_LINEAR);
+
+	handle_flag(&use_flags, BO_USE_SW_READ_OFTEN, &bind, VIRGL_BIND_LINEAR);
+	handle_flag(&use_flags, BO_USE_SW_READ_RARELY, &bind, VIRGL_BIND_LINEAR);
+	handle_flag(&use_flags, BO_USE_SW_WRITE_OFTEN, &bind, VIRGL_BIND_LINEAR);
+	handle_flag(&use_flags, BO_USE_SW_WRITE_RARELY, &bind, VIRGL_BIND_LINEAR);
+
+	// All host drivers only support linear camera buffer formats. If
+	// that changes, this will need to be modified.
+	handle_flag(&use_flags, BO_USE_CAMERA_READ, &bind, VIRGL_BIND_LINEAR);
+	handle_flag(&use_flags, BO_USE_CAMERA_WRITE, &bind, VIRGL_BIND_LINEAR);
+
+	if (use_flags) {
+		drv_log("Unhandled bo use flag: %llx\n", (unsigned long long)use_flags);
+	}
+
+	return bind;
+}
+
+static int virtio_virgl_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+				  uint64_t use_flags)
+{
+	int ret;
+	size_t i;
+	uint32_t stride;
+	struct drm_virtgpu_resource_create res_create;
+	struct bo_metadata emulated_metadata;
+
+	if (virtio_gpu_supports_combination_natively(bo->drv, format, use_flags)) {
+		stride = drv_stride_from_format(format, width, 0);
+		drv_bo_from_format(bo, stride, height, format);
+	} else {
+		assert(
+		    virtio_gpu_supports_combination_through_emulation(bo->drv, format, use_flags));
+
+		virtio_gpu_get_emulated_metadata(bo, &emulated_metadata);
+
+		format = emulated_metadata.format;
+		width = emulated_metadata.width;
+		height = emulated_metadata.height;
+		for (i = 0; i < emulated_metadata.num_planes; i++) {
+			bo->meta.strides[i] = emulated_metadata.strides[i];
+			bo->meta.offsets[i] = emulated_metadata.offsets[i];
+			bo->meta.sizes[i] = emulated_metadata.sizes[i];
+		}
+		bo->meta.total_size = emulated_metadata.total_size;
+	}
+
+	/*
+	 * Setting the target is intended to ensure this resource gets bound as a 2D
+	 * texture in the host renderer's GL state. All of these resource properties are
+	 * sent unchanged by the kernel to the host, which in turn sends them unchanged to
+	 * virglrenderer. When virglrenderer makes a resource, it will convert the target
+	 * enum to the equivalent one in GL and then bind the resource to that target.
+	 */
+	memset(&res_create, 0, sizeof(res_create));
+
+	res_create.target = PIPE_TEXTURE_2D;
+	res_create.format = translate_format(format);
+	res_create.bind = use_flags_to_bind(use_flags);
+	res_create.width = width;
+	res_create.height = height;
+
+	/* For virgl 3D */
+	res_create.depth = 1;
+	res_create.array_size = 1;
+	res_create.last_level = 0;
+	res_create.nr_samples = 0;
+
+	res_create.size = ALIGN(bo->meta.total_size, PAGE_SIZE); // PAGE_SIZE = 0x1000
+	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE, &res_create);
+	if (ret) {
+		drv_log("DRM_IOCTL_VIRTGPU_RESOURCE_CREATE failed with %s\n", strerror(errno));
+		return ret;
+	}
+
+	for (uint32_t plane = 0; plane < bo->meta.num_planes; plane++)
+		bo->handles[plane].u32 = res_create.bo_handle;
+
+	return 0;
+}
+
+static void *virtio_virgl_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
+{
+	int ret;
+	struct drm_virtgpu_map gem_map;
+
+	memset(&gem_map, 0, sizeof(gem_map));
+	gem_map.handle = bo->handles[0].u32;
+
+	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_MAP, &gem_map);
+	if (ret) {
+		drv_log("DRM_IOCTL_VIRTGPU_MAP failed with %s\n", strerror(errno));
+		return MAP_FAILED;
+	}
+
+	vma->length = bo->meta.total_size;
+	return mmap(0, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd,
+		    gem_map.offset);
+}
+
+static int virtio_gpu_get_caps(struct driver *drv, union virgl_caps *caps, int *caps_is_v2)
+{
+	int ret;
+	struct drm_virtgpu_get_caps cap_args;
+
+	*caps_is_v2 = 0;
+	memset(&cap_args, 0, sizeof(cap_args));
+	cap_args.addr = (unsigned long long)caps;
+	if (features[feat_capset_fix].enabled) {
+		*caps_is_v2 = 1;
+		cap_args.cap_set_id = 2;
+		cap_args.size = sizeof(union virgl_caps);
+	} else {
+		cap_args.cap_set_id = 1;
+		cap_args.size = sizeof(struct virgl_caps_v1);
+	}
+
+	ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GET_CAPS, &cap_args);
+	if (ret) {
+		drv_log("DRM_IOCTL_VIRTGPU_GET_CAPS failed with %s\n", strerror(errno));
+		*caps_is_v2 = 0;
+
+		// Fallback to v1
+		cap_args.cap_set_id = 1;
+		cap_args.size = sizeof(struct virgl_caps_v1);
+
+		ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GET_CAPS, &cap_args);
+		if (ret) {
+			drv_log("DRM_IOCTL_VIRTGPU_GET_CAPS failed with %s\n", strerror(errno));
+		}
+	}
+
+	return ret;
+}
+
+static void virtio_gpu_init_features_and_caps(struct driver *drv)
+{
+	struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)drv->priv;
+
+	for (uint32_t i = 0; i < ARRAY_SIZE(features); i++) {
+		struct drm_virtgpu_getparam params = { 0 };
+
+		params.param = features[i].feature;
+		params.value = (uint64_t)(uintptr_t)&features[i].enabled;
+		int ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GETPARAM, &params);
+		if (ret)
+			drv_log("DRM_IOCTL_VIRTGPU_GET_PARAM failed with %s\n", strerror(errno));
+	}
+
+	if (features[feat_3d].enabled) {
+		virtio_gpu_get_caps(drv, &priv->caps, &priv->caps_is_v2);
+	}
+
+	// Multi-planar formats are currently only supported in virglrenderer through gbm.
+	priv->host_gbm_enabled =
+	    virtio_gpu_supports_combination_natively(drv, DRM_FORMAT_NV12, BO_USE_TEXTURE);
+}
+
+static int virtio_gpu_init(struct driver *drv)
+{
+	struct virtio_gpu_priv *priv;
+
+	priv = calloc(1, sizeof(*priv));
+	drv->priv = priv;
+
+	virtio_gpu_init_features_and_caps(drv);
+
+	if (features[feat_3d].enabled) {
+		/* This doesn't mean host can scanout everything, it just means host
+		 * hypervisor can show it. */
+		virtio_gpu_add_combinations(drv, render_target_formats,
+					    ARRAY_SIZE(render_target_formats), &LINEAR_METADATA,
+					    BO_USE_RENDER_MASK | BO_USE_SCANOUT);
+		virtio_gpu_add_combinations(drv, texture_source_formats,
+					    ARRAY_SIZE(texture_source_formats), &LINEAR_METADATA,
+					    BO_USE_TEXTURE_MASK);
+	} else {
+		/* Virtio primary plane only allows this format. */
+		virtio_gpu_add_combination(drv, DRM_FORMAT_XRGB8888, &LINEAR_METADATA,
+					   BO_USE_RENDER_MASK | BO_USE_SCANOUT);
+		/* Virtio cursor plane only allows this format and Chrome cannot live without
+		 * ARGB888 renderable format. */
+		virtio_gpu_add_combination(drv, DRM_FORMAT_ARGB8888, &LINEAR_METADATA,
+					   BO_USE_RENDER_MASK | BO_USE_CURSOR);
+		/* Android needs more, but they cannot be bound as scanouts anymore after
+		 * "drm/virtio: fix DRM_FORMAT_* handling" */
+		virtio_gpu_add_combinations(drv, render_target_formats,
+					    ARRAY_SIZE(render_target_formats), &LINEAR_METADATA,
+					    BO_USE_RENDER_MASK);
+		virtio_gpu_add_combinations(drv, dumb_texture_source_formats,
+					    ARRAY_SIZE(dumb_texture_source_formats),
+					    &LINEAR_METADATA, BO_USE_TEXTURE_MASK);
+		virtio_gpu_add_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA,
+					   BO_USE_SW_MASK | BO_USE_LINEAR);
+		virtio_gpu_add_combination(drv, DRM_FORMAT_NV21, &LINEAR_METADATA,
+					   BO_USE_SW_MASK | BO_USE_LINEAR);
+	}
+
+	/* Android CTS tests require this. */
+	virtio_gpu_add_combination(drv, DRM_FORMAT_RGB888, &LINEAR_METADATA, BO_USE_SW_MASK);
+	virtio_gpu_add_combination(drv, DRM_FORMAT_BGR888, &LINEAR_METADATA, BO_USE_SW_MASK);
+	virtio_gpu_add_combination(drv, DRM_FORMAT_ABGR16161616F, &LINEAR_METADATA,
+				   BO_USE_SW_MASK | BO_USE_TEXTURE_MASK);
+
+	drv_modify_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA,
+			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER |
+				   BO_USE_HW_VIDEO_ENCODER);
+	drv_modify_combination(drv, DRM_FORMAT_NV21, &LINEAR_METADATA,
+			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER |
+				   BO_USE_HW_VIDEO_ENCODER);
+	drv_modify_combination(drv, DRM_FORMAT_YVU420, &LINEAR_METADATA,
+			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER |
+				   BO_USE_HW_VIDEO_ENCODER | BO_USE_RENDERSCRIPT);
+	drv_modify_combination(drv, DRM_FORMAT_YVU420_ANDROID, &LINEAR_METADATA,
+			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER |
+				   BO_USE_HW_VIDEO_ENCODER | BO_USE_RENDERSCRIPT);
+	drv_modify_combination(drv, DRM_FORMAT_R8, &LINEAR_METADATA,
+			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER);
+	drv_modify_combination(drv, DRM_FORMAT_R16, &LINEAR_METADATA,
+			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER);
+
+	return drv_modify_linear_combinations(drv);
+}
+
+static void virtio_gpu_close(struct driver *drv)
+{
+	free(drv->priv);
+	drv->priv = NULL;
+}
+
+static int virtio_gpu_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+				uint64_t use_flags)
+{
+	if (features[feat_3d].enabled)
+		return virtio_virgl_bo_create(bo, width, height, format, use_flags);
+	else
+		return virtio_dumb_bo_create(bo, width, height, format, use_flags);
+}
+
+static int virtio_gpu_bo_destroy(struct bo *bo)
+{
+	if (features[feat_3d].enabled)
+		return drv_gem_bo_destroy(bo);
+	else
+		return drv_dumb_bo_destroy(bo);
+}
+
+static void *virtio_gpu_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
+{
+	if (features[feat_3d].enabled)
+		return virtio_virgl_bo_map(bo, vma, plane, map_flags);
+	else
+		return drv_dumb_bo_map(bo, vma, plane, map_flags);
+}
+
+static int virtio_gpu_bo_invalidate(struct bo *bo, struct mapping *mapping)
+{
+	int ret;
+	size_t i;
+	struct drm_virtgpu_3d_transfer_from_host xfer;
+	struct drm_virtgpu_3d_wait waitcmd;
+	struct virtio_transfers_params xfer_params;
+	struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)bo->drv->priv;
+
+	if (!features[feat_3d].enabled)
+		return 0;
+
+	// Invalidate is only necessary if the host writes to the buffer.
+	if ((bo->meta.use_flags & (BO_USE_RENDERING | BO_USE_CAMERA_WRITE |
+				   BO_USE_HW_VIDEO_ENCODER | BO_USE_HW_VIDEO_DECODER)) == 0)
+		return 0;
+
+	memset(&xfer, 0, sizeof(xfer));
+	xfer.bo_handle = mapping->vma->handle;
+
+	if ((bo->meta.use_flags & BO_USE_RENDERING) == 0) {
+		// Unfortunately, the kernel doesn't actually pass the guest layer_stride
+		// and guest stride to the host (compare virtio_gpu.h and virtgpu_drm.h).
+		// For gbm based resources, we can work around this by using the level field
+		// to pass the stride to virglrenderer's gbm transfer code. However, we need
+		// to avoid doing this for resources which don't rely on that transfer code,
+		// which is resources with the BO_USE_RENDERING flag set.
+		// TODO(b/145993887): Send also stride when the patches are landed
+		if (priv->host_gbm_enabled) {
+			xfer.level = bo->meta.strides[0];
+		}
+	}
+
+	if (virtio_gpu_supports_combination_natively(bo->drv, bo->meta.format,
+						     bo->meta.use_flags)) {
+		xfer_params.xfers_needed = 1;
+		xfer_params.xfer_boxes[0] = mapping->rect;
+	} else {
+		assert(virtio_gpu_supports_combination_through_emulation(bo->drv, bo->meta.format,
+									 bo->meta.use_flags));
+
+		virtio_gpu_get_emulated_transfers_params(bo, &mapping->rect, &xfer_params);
+	}
+
+	for (i = 0; i < xfer_params.xfers_needed; i++) {
+		xfer.box.x = xfer_params.xfer_boxes[i].x;
+		xfer.box.y = xfer_params.xfer_boxes[i].y;
+		xfer.box.w = xfer_params.xfer_boxes[i].width;
+		xfer.box.h = xfer_params.xfer_boxes[i].height;
+		xfer.box.d = 1;
+
+		ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST, &xfer);
+		if (ret) {
+			drv_log("DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST failed with %s\n",
+				strerror(errno));
+			return -errno;
+		}
+	}
+
+	// The transfer needs to complete before invalidate returns so that any host changes
+	// are visible and to ensure the host doesn't overwrite subsequent guest changes.
+	// TODO(b/136733358): Support returning fences from transfers
+	memset(&waitcmd, 0, sizeof(waitcmd));
+	waitcmd.handle = mapping->vma->handle;
+	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_WAIT, &waitcmd);
+	if (ret) {
+		drv_log("DRM_IOCTL_VIRTGPU_WAIT failed with %s\n", strerror(errno));
+		return -errno;
+	}
+
+	return 0;
+}
+
+static int virtio_gpu_bo_flush(struct bo *bo, struct mapping *mapping)
+{
+	int ret;
+	size_t i;
+	struct drm_virtgpu_3d_transfer_to_host xfer;
+	struct drm_virtgpu_3d_wait waitcmd;
+	struct virtio_transfers_params xfer_params;
+	struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)bo->drv->priv;
+
+	if (!features[feat_3d].enabled)
+		return 0;
+
+	if (!(mapping->vma->map_flags & BO_MAP_WRITE))
+		return 0;
+
+	memset(&xfer, 0, sizeof(xfer));
+	xfer.bo_handle = mapping->vma->handle;
+
+	// Unfortunately, the kernel doesn't actually pass the guest layer_stride and
+	// guest stride to the host (compare virtio_gpu.h and virtgpu_drm.h). We can use
+	// the level to work around this.
+	if (priv->host_gbm_enabled) {
+		xfer.level = bo->meta.strides[0];
+	}
+
+	if (virtio_gpu_supports_combination_natively(bo->drv, bo->meta.format,
+						     bo->meta.use_flags)) {
+		xfer_params.xfers_needed = 1;
+		xfer_params.xfer_boxes[0] = mapping->rect;
+	} else {
+		assert(virtio_gpu_supports_combination_through_emulation(bo->drv, bo->meta.format,
+									 bo->meta.use_flags));
+
+		virtio_gpu_get_emulated_transfers_params(bo, &mapping->rect, &xfer_params);
+	}
+
+	for (i = 0; i < xfer_params.xfers_needed; i++) {
+		xfer.box.x = xfer_params.xfer_boxes[i].x;
+		xfer.box.y = xfer_params.xfer_boxes[i].y;
+		xfer.box.w = xfer_params.xfer_boxes[i].width;
+		xfer.box.h = xfer_params.xfer_boxes[i].height;
+		xfer.box.d = 1;
+
+		ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST, &xfer);
+		if (ret) {
+			drv_log("DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST failed with %s\n",
+				strerror(errno));
+			return -errno;
+		}
+	}
+
+	// If the buffer is only accessed by the host GPU, then the flush is ordered
+	// with subsequent commands. However, if other host hardware can access the
+	// buffer, we need to wait for the transfer to complete for consistency.
+	// TODO(b/136733358): Support returning fences from transfers
+	if (bo->meta.use_flags & BO_USE_NON_GPU_HW) {
+		memset(&waitcmd, 0, sizeof(waitcmd));
+		waitcmd.handle = mapping->vma->handle;
+
+		ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_WAIT, &waitcmd);
+		if (ret) {
+			drv_log("DRM_IOCTL_VIRTGPU_WAIT failed with %s\n", strerror(errno));
+			return -errno;
+		}
+	}
+
+	return 0;
+}
+
+static uint32_t virtio_gpu_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags)
+{
+	switch (format) {
+	case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
+		/* Camera subsystem requires NV12. */
+		if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE))
+			return DRM_FORMAT_NV12;
+		/*HACK: See b/28671744 */
+		return DRM_FORMAT_XBGR8888;
+	case DRM_FORMAT_FLEX_YCbCr_420_888:
+		/*
+		 * All of our host drivers prefer NV12 as their flexible media format.
+		 * If that changes, this will need to be modified.
+		 */
+		if (features[feat_3d].enabled)
+			return DRM_FORMAT_NV12;
+		else
+			return DRM_FORMAT_YVU420_ANDROID;
+	default:
+		return format;
+	}
+}
+
+static int virtio_gpu_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES],
+				    uint32_t offsets[DRV_MAX_PLANES])
+{
+	int ret;
+	struct drm_virtgpu_resource_info res_info;
+
+	if (!features[feat_3d].enabled)
+		return 0;
+
+	memset(&res_info, 0, sizeof(res_info));
+	res_info.bo_handle = bo->handles[0].u32;
+	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_INFO, &res_info);
+	if (ret) {
+		drv_log("DRM_IOCTL_VIRTGPU_RESOURCE_INFO failed with %s\n", strerror(errno));
+		return ret;
+	}
+
+	for (uint32_t plane = 0; plane < bo->meta.num_planes; plane++) {
+		/*
+		 * Currently, kernel v4.14 (Betty) doesn't have the extended resource info
+		 * ioctl.
+		 */
+		if (res_info.strides[plane]) {
+			strides[plane] = res_info.strides[plane];
+			offsets[plane] = res_info.offsets[plane];
+		}
+	}
+
+	return 0;
+}
+
+const struct backend backend_virtio_gpu = {
+	.name = "virtio_gpu",
+	.init = virtio_gpu_init,
+	.close = virtio_gpu_close,
+	.bo_create = virtio_gpu_bo_create,
+	.bo_destroy = virtio_gpu_bo_destroy,
+	.bo_import = drv_prime_bo_import,
+	.bo_map = virtio_gpu_bo_map,
+	.bo_unmap = drv_bo_munmap,
+	.bo_invalidate = virtio_gpu_bo_invalidate,
+	.bo_flush = virtio_gpu_bo_flush,
+	.resolve_format = virtio_gpu_resolve_format,
+	.resource_info = virtio_gpu_resource_info,
+};