Snap for 7981408 from d1770ed2e4fbb4e88f90d6b7086f5ec56cdc00d2 to sc-v2-release

Change-Id: I42b1ccf388040b06beab25790f5f7b69b9aeaf6a
diff --git a/Android.bp b/Android.bp
index e7dfff8..9eb75e5 100644
--- a/Android.bp
+++ b/Android.bp
@@ -32,16 +32,15 @@
     ],
 }
 
-cc_defaults {
-    name: "minigbm_defaults",
+filegroup {
+    name: "minigbm_core_files",
 
     srcs: [
         "amdgpu.c",
         "drv.c",
+        "drv_array_helpers.c",
+        "drv_helpers.c",
         "dumb_driver.c",
-        "exynos.c",
-        "helpers_array.c",
-        "helpers.c",
         "i915.c",
         "mediatek.c",
         "msm.c",
@@ -51,6 +50,25 @@
         "virtgpu_cross_domain.c",
         "virtgpu_virgl.c",
     ],
+}
+
+filegroup {
+    name: "minigbm_gralloc_common_files",
+
+    srcs: [
+        "cros_gralloc/cros_gralloc_buffer.cc",
+        "cros_gralloc/cros_gralloc_helpers.cc",
+        "cros_gralloc/cros_gralloc_driver.cc",
+    ],
+}
+
+filegroup {
+    name: "minigbm_gralloc0_files",
+    srcs: ["cros_gralloc/gralloc0/gralloc0.cc"],
+}
+
+cc_defaults {
+    name: "minigbm_defaults",
 
     cflags: [
         "-D_GNU_SOURCE=1",
@@ -63,7 +81,18 @@
         "-Wno-unused-parameter",
     ],
 
-    cppflags: ["-std=c++14"],
+    product_variables: {
+        platform_sdk_version: {
+            cflags: ["-DANDROID_API_LEVEL=%d"],
+        },
+    },
+}
+
+cc_library_headers {
+    name: "minigbm_headers",
+    host_supported: true,
+    vendor_available: true,
+    export_include_dirs: ["."],
 }
 
 cc_defaults {
@@ -74,27 +103,12 @@
     header_libs: [
         "libhardware_headers",
         "libnativebase_headers",
-        "libnativewindow_headers",
         "libsystem_headers",
-    ],
-
-    export_header_lib_headers: [
-        "libhardware_headers",
-        "libnativebase_headers",
-        "libnativewindow_headers",
-        "libsystem_headers",
-    ],
-
-    srcs: [
-        "cros_gralloc/cros_gralloc_buffer.cc",
-        "cros_gralloc/cros_gralloc_helpers.cc",
-        "cros_gralloc/cros_gralloc_driver.cc",
+        "minigbm_headers",
     ],
 
     static_libs: ["libarect"],
 
-    export_static_lib_headers: ["libarect"],
-
     vendor: true,
 
     shared_libs: [
@@ -104,28 +118,38 @@
         "libsync",
         "liblog",
     ],
-
-    relative_install_path: "hw",
 }
 
 cc_defaults {
-    name: "gbm_defaults",
+    name: "minigbm_cros_gralloc_library_defaults",
 
-    defaults: ["minigbm_defaults"],
-
+    defaults: ["minigbm_cros_gralloc_defaults"],
     srcs: [
-        "gbm.c",
-        "gbm_helpers.c",
+        ":minigbm_core_files",
+        ":minigbm_gralloc_common_files",
     ],
+}
 
-    export_include_dirs: ["."],
+cc_defaults {
+    name: "minigbm_cros_gralloc0_defaults",
+
+    defaults: ["minigbm_cros_gralloc_defaults"],
+    relative_install_path: "hw",
+
+    srcs: [":minigbm_gralloc0_files"],
 }
 
 cc_library {
     name: "libgbm",
-    defaults: ["gbm_defaults"],
+    defaults: ["minigbm_defaults"],
     host_supported: true,
 
+    srcs: [
+        ":minigbm_core_files",
+        "gbm.c",
+        "gbm_helpers.c",
+    ],
+
     target: {
         host: {
             // Avoid linking to another host copy of libdrm; this library will cause
@@ -145,31 +169,27 @@
         "//apex_available:platform",
         "com.android.virt",
     ],
-}
-
-cc_defaults {
-    name: "libminigbm_cros_gralloc_defaults",
-    defaults: ["minigbm_cros_gralloc_defaults"],
-    shared_libs: ["liblog"],
-    static_libs: ["libdrm"],
 
     export_include_dirs: ["."],
 }
 
-cc_library_static {
-    name: "libminigbm_cros_gralloc",
-    defaults: ["libminigbm_cros_gralloc_defaults"],
+// Generic
+cc_library_shared {
+    name: "libminigbm_gralloc",
+    defaults: ["minigbm_cros_gralloc_library_defaults"],
 }
 
 cc_library_shared {
     name: "gralloc.minigbm",
-    defaults: ["minigbm_cros_gralloc_defaults"],
-    srcs: ["cros_gralloc/gralloc0/gralloc0.cc"],
+    defaults: ["minigbm_cros_gralloc0_defaults"],
+    shared_libs: ["libminigbm_gralloc"],
 }
 
+// Intel
 cc_library_shared {
-    name: "gralloc.minigbm_intel",
-    defaults: ["minigbm_cros_gralloc_defaults"],
+    name: "libminigbm_gralloc_intel",
+    defaults: ["minigbm_cros_gralloc_library_defaults"],
+    cflags: ["-DDRV_I915"],
     enabled: false,
     arch: {
         x86: {
@@ -179,28 +199,61 @@
             enabled: true,
         },
     },
-    cflags: ["-DDRV_I915"],
-    srcs: ["cros_gralloc/gralloc0/gralloc0.cc"],
+}
+
+cc_library_shared {
+    name: "gralloc.minigbm_intel",
+    defaults: ["minigbm_cros_gralloc0_defaults"],
+    shared_libs: ["libminigbm_gralloc_intel"],
+    enabled: false,
+    arch: {
+        x86: {
+            enabled: true,
+        },
+        x86_64: {
+            enabled: true,
+        },
+    },
+}
+
+// Meson
+cc_library_shared {
+    name: "libminigbm_gralloc_meson",
+    defaults: ["minigbm_cros_gralloc_library_defaults"],
+    cflags: ["-DDRV_MESON"],
 }
 
 cc_library_shared {
     name: "gralloc.minigbm_meson",
-    defaults: ["minigbm_cros_gralloc_defaults"],
-    cflags: ["-DDRV_MESON"],
-    srcs: ["cros_gralloc/gralloc0/gralloc0.cc"],
+    defaults: ["minigbm_cros_gralloc0_defaults"],
+    shared_libs: ["libminigbm_gralloc_meson"],
+}
+
+// MSM
+cc_library_shared {
+    name: "libminigbm_gralloc_msm",
+    defaults: ["minigbm_cros_gralloc_library_defaults"],
+    cflags: [
+        "-DDRV_MSM",
+        "-DQCOM_DISABLE_COMPRESSED_NV12",
+    ],
 }
 
 cc_library_shared {
     name: "gralloc.minigbm_msm",
-    defaults: ["minigbm_cros_gralloc_defaults"],
-    cflags: ["-DDRV_MSM"],
-    srcs: [
-        "cros_gralloc/gralloc0/gralloc0.cc",
-    ],
+    defaults: ["minigbm_cros_gralloc0_defaults"],
+    shared_libs: ["libminigbm_gralloc_msm"],
 }
 
-cc_library_static {
-    name: "libminigbm_cros_gralloc_msm",
-    defaults: ["libminigbm_cros_gralloc_defaults"],
-    cflags: ["-DDRV_MSM"],
+// ARCVM
+cc_library_shared {
+    name: "libminigbm_gralloc_arcvm",
+    defaults: ["minigbm_cros_gralloc_library_defaults"],
+    cflags: ["-DVIRTIO_GPU_NEXT"],
+}
+
+cc_library_shared {
+    name: "gralloc.minigbm_arcvm",
+    defaults: ["minigbm_cros_gralloc0_defaults"],
+    shared_libs: ["libminigbm_gralloc_arcvm"],
 }
diff --git a/Android.gralloc.mk b/Android.gralloc.mk
deleted file mode 100644
index ff269c0..0000000
--- a/Android.gralloc.mk
+++ /dev/null
@@ -1,11 +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.
-
-LOCAL_CPP_EXTENSION := .cc
-
-LOCAL_SRC_FILES += \
-	cros_gralloc/cros_gralloc_buffer.cc \
-	cros_gralloc/cros_gralloc_driver.cc \
-	cros_gralloc/cros_gralloc_helpers.cc \
-	cros_gralloc/gralloc0/gralloc0.cc
diff --git a/Makefile b/Makefile
index 8238026..987708f 100644
--- a/Makefile
+++ b/Makefile
@@ -16,9 +16,6 @@
 	CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_amdgpu)
 	LDLIBS += -ldrm_amdgpu -ldl
 endif
-ifdef DRV_EXYNOS
-	CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_exynos)
-endif
 ifdef DRV_I915
 	CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_intel)
 endif
@@ -49,6 +46,7 @@
 
 CC_LIBRARY($(MINIGBM_FILENAME)): LDFLAGS += -Wl,-soname,libgbm.so.$(GBM_VERSION_MAJOR)
 CC_LIBRARY($(MINIGBM_FILENAME)): $(C_OBJECTS)
+CC_STATIC_LIBRARY(libminigbm.pie.a): $(C_OBJECTS)
 
 all: CC_LIBRARY($(MINIGBM_FILENAME))
 
diff --git a/OWNERS b/OWNERS
index 6a69a37..1facc15 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,10 +1,20 @@
+basni@chromium.org
+dbehr@chromium.org
+ddavenport@chromium.org
 gurchetansingh@chromium.org
+hiroh@chromium.org
 hoegsberg@chromium.org
 marcheu@chromium.org
+olv@google.com
+robdclark@chromium.org
 stevensd@chromium.org
 tfiga@chromium.org
+zzyiwei@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
-*
+# just reference for backend specific reviews
+per-file amdgpu.c = basni@chromium.org, ddavenport@chromium.org
+per-file i915.c = chadversary@chromium.org, hoegsberg@chromium.org
+per-file mediatek.c = fshao@chromium.org, tzungbi@chromium.org
+per-file msm.c = robdclark@chromium.org, hoegsberg@chromium.org
+per-file rockchip.c = tfiga@chromium.org
+per-file virtgpu* = jbates@chromium.org, natsu@google.com, olv@google.com, zzyiwei@chromium.org
diff --git a/amdgpu.c b/amdgpu.c
index f987f6f..f0053d6 100644
--- a/amdgpu.c
+++ b/amdgpu.c
@@ -6,16 +6,21 @@
 #ifdef DRV_AMDGPU
 #include <amdgpu.h>
 #include <amdgpu_drm.h>
+#include <assert.h>
+#include <drm_fourcc.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/mman.h>
+#include <unistd.h>
 #include <xf86drm.h>
+#include <xf86drmMode.h>
 
 #include "dri.h"
+#include "drv_helpers.h"
 #include "drv_priv.h"
-#include "helpers.h"
 #include "util.h"
 
 // clang-format off
@@ -23,8 +28,10 @@
 // clang-format on
 
 #define TILE_TYPE_LINEAR 0
+/* We decide a modifier and then use DRI to manage allocation */
+#define TILE_TYPE_DRI_MODIFIER 1
 /* DRI backend decides tiling in this case. */
-#define TILE_TYPE_DRI 1
+#define TILE_TYPE_DRI 2
 
 /* Height alignement for Encoder/Decoder buffers */
 #define CHROME_HEIGHT_ALIGN 16
@@ -305,6 +312,39 @@
 	return ret;
 }
 
+static bool is_modifier_scanout_capable(struct amdgpu_priv *priv, uint32_t format,
+					uint64_t modifier)
+{
+	unsigned bytes_per_pixel = drv_stride_from_format(format, 1, 0);
+
+	if (modifier == DRM_FORMAT_MOD_LINEAR)
+		return true;
+
+	if ((modifier >> 56) != DRM_FORMAT_MOD_VENDOR_AMD)
+		return false;
+
+	unsigned swizzle = AMD_FMT_MOD_GET(TILE, modifier);
+	if (priv->dev_info.family >= AMDGPU_FAMILY_RV) { /* DCN based GPUs */
+		/* D swizzle only supported for 64 bpp */
+		if ((swizzle & 3) == 2 && bytes_per_pixel != 8)
+			return false;
+
+		/* S swizzle not supported for 64 bpp */
+		if ((swizzle & 3) == 1 && bytes_per_pixel == 8)
+			return false;
+	} else { /* DCE based GPUs with GFX9 based modifier swizzling. */
+		assert(priv->dev_info.family == AMDGPU_FAMILY_AI);
+		/* Only D swizzles are allowed for display */
+		if ((swizzle & 3) != 2)
+			return false;
+	}
+
+	if (AMD_FMT_MOD_GET(DCC, modifier) &&
+	    (AMD_FMT_MOD_GET(DCC_PIPE_ALIGN, modifier) || !AMD_FMT_MOD_GET(DCC_RETILE, modifier)))
+		return false;
+	return true;
+}
+
 static int amdgpu_init(struct driver *drv)
 {
 	struct amdgpu_priv *priv;
@@ -370,6 +410,7 @@
 	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_RGB565, &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);
@@ -394,24 +435,60 @@
 	use_flags &= ~BO_USE_RENDERSCRIPT;
 	use_flags &= ~BO_USE_SW_WRITE_OFTEN;
 	use_flags &= ~BO_USE_SW_READ_OFTEN;
+#if __ANDROID__
+	use_flags &= ~BO_USE_SW_WRITE_RARELY;
+	use_flags &= ~BO_USE_SW_READ_RARELY;
+#endif
 	use_flags &= ~BO_USE_LINEAR;
 
-	metadata.tiling = TILE_TYPE_DRI;
 	metadata.priority = 2;
 
-	drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
-			     &metadata, use_flags);
+	for (unsigned f = 0; f < ARRAY_SIZE(render_target_formats); ++f) {
+		uint32_t format = render_target_formats[f];
+		int mod_cnt;
+		if (dri_query_modifiers(drv, format, 0, NULL, &mod_cnt) && mod_cnt) {
+			uint64_t *modifiers = calloc(mod_cnt, sizeof(uint64_t));
+			dri_query_modifiers(drv, format, mod_cnt, modifiers, &mod_cnt);
+			metadata.tiling = TILE_TYPE_DRI_MODIFIER;
+			for (int i = 0; i < mod_cnt; ++i) {
+				bool scanout =
+				    is_modifier_scanout_capable(drv->priv, format, modifiers[i]);
 
-	/* Potentially tiled formats supported by display. */
-	drv_modify_combination(drv, DRM_FORMAT_ARGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT);
-	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);
+				/* LINEAR will be handled using the LINEAR metadata. */
+				if (modifiers[i] == DRM_FORMAT_MOD_LINEAR)
+					continue;
 
-	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);
+				/* The virtgpu minigbm can't handle auxiliary planes in the host. */
+				if (dri_num_planes_from_modifier(drv, format, modifiers[i]) !=
+				    drv_num_planes_from_format(format))
+					continue;
+
+				metadata.modifier = modifiers[i];
+				drv_add_combination(drv, format, &metadata,
+						    use_flags | (scanout ? BO_USE_SCANOUT : 0));
+			}
+			free(modifiers);
+		} else {
+			bool scanout = false;
+			switch (format) {
+			case DRM_FORMAT_ARGB8888:
+			case DRM_FORMAT_XRGB8888:
+			case DRM_FORMAT_ABGR8888:
+			case DRM_FORMAT_XBGR8888:
+			case DRM_FORMAT_ABGR2101010:
+			case DRM_FORMAT_ARGB2101010:
+			case DRM_FORMAT_XBGR2101010:
+			case DRM_FORMAT_XRGB2101010:
+				scanout = true;
+				break;
+			default:
+				break;
+			}
+			metadata.tiling = TILE_TYPE_DRI;
+			drv_add_combination(drv, format, &metadata,
+					    use_flags | (scanout ? BO_USE_SCANOUT : 0));
+		}
+	}
 	return 0;
 }
 
@@ -439,9 +516,11 @@
 	 * 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).
+	 * families, but let's restrict it to Raven and Stoney for now (b/171013552, b/190484589).
 	 * */
-	if (priv->dev_info.family == AMDGPU_FAMILY_RV && num_planes > 1)
+	if (num_planes > 1 &&
+	    (priv->dev_info.family == AMDGPU_FAMILY_RV ||
+	     (priv->dev_info.family == AMDGPU_FAMILY_CZ && !(use_flags & BO_USE_HW_VIDEO_ENCODER))))
 		stride = ALIGN(stride, 512);
 	else
 		stride = ALIGN(stride, 256);
@@ -503,28 +582,16 @@
 		return -EINVAL;
 
 	if (combo->metadata.tiling == TILE_TYPE_DRI) {
-		bool needs_alignment = false;
-#ifdef __ANDROID__
-		/*
-		 * Currently, the gralloc API doesn't differentiate between allocation time and map
-		 * time strides. A workaround for amdgpu DRI buffers is to always to align to 256 at
-		 * allocation time.
-		 *
-		 * See b/115946221,b/117942643
-		 */
-		if (use_flags & (BO_USE_SW_MASK))
-			needs_alignment = true;
-#endif
 		// See b/122049612
-		if (use_flags & (BO_USE_SCANOUT) && priv->dev_info.family == AMDGPU_FAMILY_CZ)
-			needs_alignment = true;
-
-		if (needs_alignment) {
+		if (use_flags & (BO_USE_SCANOUT) && priv->dev_info.family == AMDGPU_FAMILY_CZ) {
 			uint32_t bytes_per_pixel = drv_bytes_per_pixel_from_format(format, 0);
 			width = ALIGN(width, 256 / bytes_per_pixel);
 		}
 
 		return dri_bo_create(bo, width, height, format, use_flags);
+	} else if (combo->metadata.tiling == TILE_TYPE_DRI_MODIFIER) {
+		return dri_bo_create_with_modifiers(bo, width, height, format,
+						    &combo->metadata.modifier, 1);
 	}
 
 	return amdgpu_create_bo_linear(bo, width, height, format, use_flags);
@@ -555,7 +622,7 @@
 		if (!combo)
 			return -EINVAL;
 
-		dri_tiling = combo->metadata.tiling == TILE_TYPE_DRI;
+		dri_tiling = combo->metadata.tiling != TILE_TYPE_LINEAR;
 	}
 
 	if (dri_tiling)
@@ -564,6 +631,14 @@
 		return drv_prime_bo_import(bo, data);
 }
 
+static int amdgpu_release_bo(struct bo *bo)
+{
+	if (bo->priv)
+		return dri_bo_release(bo);
+
+	return 0;
+}
+
 static int amdgpu_destroy_bo(struct bo *bo)
 {
 	if (bo->priv)
@@ -713,12 +788,13 @@
 	.close = amdgpu_close,
 	.bo_create = amdgpu_create_bo,
 	.bo_create_with_modifiers = amdgpu_create_bo_with_modifiers,
+	.bo_release = amdgpu_release_bo,
 	.bo_destroy = amdgpu_destroy_bo,
 	.bo_import = amdgpu_import_bo,
 	.bo_map = amdgpu_map_bo,
 	.bo_unmap = amdgpu_unmap_bo,
 	.bo_invalidate = amdgpu_bo_invalidate,
-	.resolve_format = drv_resolve_format_helper,
+	.resolve_format_and_use_flags = drv_resolve_format_and_use_flags_helper,
 	.num_planes_from_modifier = dri_num_planes_from_modifier,
 };
 
diff --git a/cros_gralloc/OWNERS b/cros_gralloc/OWNERS
new file mode 100644
index 0000000..cd8d003
--- /dev/null
+++ b/cros_gralloc/OWNERS
@@ -0,0 +1,3 @@
+set noparent
+natsu@google.com
+zzyiwei@chromium.org
diff --git a/cros_gralloc/cros_gralloc_buffer.h b/cros_gralloc/cros_gralloc_buffer.h
index 9bc0ef0..3158454 100644
--- a/cros_gralloc/cros_gralloc_buffer.h
+++ b/cros_gralloc/cros_gralloc_buffer.h
@@ -7,7 +7,6 @@
 #ifndef CROS_GRALLOC_BUFFER_H
 #define CROS_GRALLOC_BUFFER_H
 
-#include "../drv.h"
 #include "cros_gralloc_helpers.h"
 
 class cros_gralloc_buffer
diff --git a/cros_gralloc/cros_gralloc_driver.cc b/cros_gralloc/cros_gralloc_driver.cc
index f0c0392..1381ff5 100644
--- a/cros_gralloc/cros_gralloc_driver.cc
+++ b/cros_gralloc/cros_gralloc_driver.cc
@@ -8,12 +8,11 @@
 
 #include <cstdlib>
 #include <fcntl.h>
+#include <hardware/gralloc.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
@@ -45,21 +44,16 @@
 	return fd;
 }
 
-cros_gralloc_driver::cros_gralloc_driver() : drv_(nullptr)
+cros_gralloc_driver *cros_gralloc_driver::get_instance()
 {
-}
+	static cros_gralloc_driver s_instance;
 
-cros_gralloc_driver::~cros_gralloc_driver()
-{
-	buffers_.clear();
-	handles_.clear();
-
-	if (drv_) {
-		int fd = drv_get_fd(drv_);
-		drv_destroy(drv_);
-		drv_ = nullptr;
-		close(fd);
+	if (!s_instance.is_initialized()) {
+		drv_log("Failed to initialize driver.\n");
+		return nullptr;
 	}
+
+	return &s_instance;
 }
 
 static struct driver *init_try_node(int idx, char const *str)
@@ -84,7 +78,7 @@
 	return drv;
 }
 
-int32_t cros_gralloc_driver::init()
+cros_gralloc_driver::cros_gralloc_driver()
 {
 	/*
 	 * Create a driver from render nodes first, then try card
@@ -105,26 +99,82 @@
 	for (uint32_t i = min_render_node; i < max_render_node; i++) {
 		drv_ = init_try_node(i, render_nodes_fmt);
 		if (drv_)
-			return 0;
+			return;
 	}
 
 	// 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;
+			return;
 	}
+}
 
-	return -ENODEV;
+cros_gralloc_driver::~cros_gralloc_driver()
+{
+	buffers_.clear();
+	handles_.clear();
+
+	if (drv_) {
+		int fd = drv_get_fd(drv_);
+		drv_destroy(drv_);
+		drv_ = nullptr;
+		close(fd);
+	}
+}
+
+bool cros_gralloc_driver::is_initialized()
+{
+	return drv_ != nullptr;
+}
+
+bool cros_gralloc_driver::get_resolved_format_and_use_flags(
+    const struct cros_gralloc_buffer_descriptor *descriptor, uint32_t *out_format,
+    uint64_t *out_use_flags)
+{
+	uint32_t resolved_format;
+	uint64_t resolved_use_flags;
+	struct combination *combo;
+
+	drv_resolve_format_and_use_flags(drv_, descriptor->drm_format, descriptor->use_flags,
+					 &resolved_format, &resolved_use_flags);
+
+	combo = drv_get_combination(drv_, resolved_format, resolved_use_flags);
+	if (!combo && (descriptor->droid_usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) &&
+	    descriptor->droid_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.
+		resolved_use_flags &= ~BO_USE_HW_VIDEO_ENCODER;
+		combo = drv_get_combination(drv_, resolved_format, resolved_use_flags);
+	}
+	if (!combo && (descriptor->droid_usage & BUFFER_USAGE_FRONT_RENDERING)) {
+		resolved_use_flags &= ~BO_USE_FRONT_RENDERING;
+		resolved_use_flags |= BO_USE_LINEAR;
+		combo = drv_get_combination(drv_, resolved_format, resolved_use_flags);
+	}
+	if (!combo)
+		return false;
+
+	*out_format = resolved_format;
+	*out_use_flags = resolved_use_flags;
+	return true;
 }
 
 bool cros_gralloc_driver::is_supported(const struct cros_gralloc_buffer_descriptor *descriptor)
 {
-	struct combination *combo;
 	uint32_t resolved_format;
-	resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags);
-	combo = drv_get_combination(drv_, resolved_format, descriptor->use_flags);
-	return (combo != nullptr);
+	uint64_t resolved_use_flags;
+	uint32_t max_texture_size = drv_get_max_texture_2d_size(drv_);
+	if (!get_resolved_format_and_use_flags(descriptor, &resolved_format, &resolved_use_flags))
+		return false;
+
+	// Allow blob buffers to go beyond the limit.
+	if (descriptor->droid_format == HAL_PIXEL_FORMAT_BLOB)
+		return true;
+
+	return descriptor->width <= max_texture_size && descriptor->height <= max_texture_size;
 }
 
 int32_t create_reserved_region(const std::string &buffer_name, uint64_t reserved_region_size)
@@ -163,24 +213,18 @@
 	size_t num_bytes;
 	uint32_t resolved_format;
 	uint32_t bytes_per_pixel;
-	uint64_t use_flags;
+	uint64_t resolved_use_flags;
 	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;
-
-	/*
-	 * This unmask is a backup in the case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED is resolved
-	 * to non-YUV formats.
-	 */
-	if (descriptor->drm_format == DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED &&
-	    (resolved_format == DRM_FORMAT_XBGR8888 || resolved_format == DRM_FORMAT_ABGR8888)) {
-		use_flags &= ~BO_USE_HW_VIDEO_ENCODER;
+	if (!get_resolved_format_and_use_flags(descriptor, &resolved_format, &resolved_use_flags)) {
+		drv_log("Failed to resolve format and use_flags.\n");
+		return -EINVAL;
 	}
 
-	bo = drv_bo_create(drv_, descriptor->width, descriptor->height, resolved_format, use_flags);
+	bo = drv_bo_create(drv_, descriptor->width, descriptor->height, resolved_format,
+			   resolved_use_flags);
 	if (!bo) {
 		drv_log("Failed to create bo.\n");
 		return -errno;
@@ -243,15 +287,15 @@
 	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->tiling = drv_bo_get_tiling(bo);
 	hnd->format_modifier = drv_bo_get_format_modifier(bo);
-	hnd->use_flags = descriptor->use_flags;
+	hnd->use_flags = drv_bo_get_use_flags(bo);
 	bytes_per_pixel = drv_bytes_per_pixel_from_format(hnd->format, 0);
 	hnd->pixel_stride = DIV_ROUND_UP(hnd->strides[0], bytes_per_pixel);
 	hnd->magic = cros_gralloc_magic;
 	hnd->droid_format = descriptor->droid_format;
 	hnd->usage = descriptor->droid_usage;
-	hnd->total_size = descriptor->reserved_region_size + bo->meta.total_size;
+	hnd->total_size = descriptor->reserved_region_size + drv_bo_get_total_size(bo);
 	hnd->name_offset = handle_data_size;
 
 	name = (char *)(&hnd->data[hnd->name_offset]);
@@ -506,9 +550,15 @@
 	return buffer->get_reserved_region(reserved_region_addr, reserved_region_size);
 }
 
-uint32_t cros_gralloc_driver::get_resolved_drm_format(uint32_t drm_format, uint64_t usage)
+uint32_t cros_gralloc_driver::get_resolved_drm_format(uint32_t drm_format, uint64_t use_flags)
 {
-	return drv_resolve_format(drv_, drm_format, usage);
+	uint32_t resolved_format;
+	uint64_t resolved_use_flags;
+
+	drv_resolve_format_and_use_flags(drv_, drm_format, use_flags, &resolved_format,
+					 &resolved_use_flags);
+
+	return resolved_format;
 }
 
 cros_gralloc_buffer *cros_gralloc_driver::get_buffer(cros_gralloc_handle_t hnd)
diff --git a/cros_gralloc/cros_gralloc_driver.h b/cros_gralloc/cros_gralloc_driver.h
index ef9e21f..d1456a8 100644
--- a/cros_gralloc/cros_gralloc_driver.h
+++ b/cros_gralloc/cros_gralloc_driver.h
@@ -16,10 +16,7 @@
 class cros_gralloc_driver
 {
       public:
-	cros_gralloc_driver();
-	~cros_gralloc_driver();
-
-	int32_t init();
+	static cros_gralloc_driver *get_instance();
 	bool is_supported(const struct cros_gralloc_buffer_descriptor *descriptor);
 	int32_t allocate(const struct cros_gralloc_buffer_descriptor *descriptor,
 			 buffer_handle_t *out_handle);
@@ -42,17 +39,21 @@
 	int32_t get_reserved_region(buffer_handle_t handle, void **reserved_region_addr,
 				    uint64_t *reserved_region_size);
 
-	uint32_t get_resolved_drm_format(uint32_t drm_format, uint64_t usage);
+	uint32_t get_resolved_drm_format(uint32_t drm_format, uint64_t use_flags);
 
 	void for_each_handle(const std::function<void(cros_gralloc_handle_t)> &function);
 
       private:
-	cros_gralloc_driver(cros_gralloc_driver const &);
-	cros_gralloc_driver operator=(cros_gralloc_driver const &);
+	cros_gralloc_driver();
+	~cros_gralloc_driver();
+	bool is_initialized();
 	cros_gralloc_buffer *get_buffer(cros_gralloc_handle_t hnd);
 	void emplace_buffer(struct bo *bo, struct cros_gralloc_handle *hnd);
+	bool
+	get_resolved_format_and_use_flags(const struct cros_gralloc_buffer_descriptor *descriptor,
+					  uint32_t *out_format, uint64_t *out_use_flags);
 
-	struct driver *drv_;
+	struct driver *drv_ = nullptr;
 	std::mutex mutex_;
 	std::unordered_map<uint32_t, cros_gralloc_buffer *> buffers_;
 	std::unordered_map<cros_gralloc_handle_t, std::pair<cros_gralloc_buffer *, int32_t>>
diff --git a/cros_gralloc/cros_gralloc_helpers.cc b/cros_gralloc/cros_gralloc_helpers.cc
index 4319936..3301522 100644
--- a/cros_gralloc/cros_gralloc_helpers.cc
+++ b/cros_gralloc/cros_gralloc_helpers.cc
@@ -6,8 +6,15 @@
 
 #include "cros_gralloc_helpers.h"
 
+#include <hardware/gralloc.h>
 #include <sync/sync.h>
 
+/* Define to match AIDL BufferUsage::VIDEO_DECODER. */
+#define BUFFER_USAGE_VIDEO_DECODER (1 << 22)
+
+/* Define to match AIDL BufferUsage::GPU_DATA_BUFFER. */
+#define BUFFER_USAGE_GPU_DATA_BUFFER (1 << 24)
+
 uint32_t cros_gralloc_convert_format(int format)
 {
 	/*
@@ -16,24 +23,27 @@
 	 */
 
 	switch (format) {
-	case HAL_PIXEL_FORMAT_BGRA_8888:
-		return DRM_FORMAT_ARGB8888;
-	case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
-		return DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED;
-	case HAL_PIXEL_FORMAT_RAW16:
-		return DRM_FORMAT_R16;
-	case HAL_PIXEL_FORMAT_RGB_565:
-		return DRM_FORMAT_RGB565;
-	case HAL_PIXEL_FORMAT_RGB_888:
-		return DRM_FORMAT_BGR888;
 	case HAL_PIXEL_FORMAT_RGBA_8888:
 		return DRM_FORMAT_ABGR8888;
 	case HAL_PIXEL_FORMAT_RGBX_8888:
 		return DRM_FORMAT_XBGR8888;
-	case HAL_PIXEL_FORMAT_YCbCr_420_888:
-		return DRM_FORMAT_FLEX_YCbCr_420_888;
-	case HAL_PIXEL_FORMAT_YV12:
-		return DRM_FORMAT_YVU420_ANDROID;
+	case HAL_PIXEL_FORMAT_RGB_888:
+		return DRM_FORMAT_BGR888;
+	/*
+	 * Confusingly, HAL_PIXEL_FORMAT_RGB_565 is defined as:
+	 *
+	 * "16-bit packed format that has 5-bit R, 6-bit G, and 5-bit B components, in that
+	 *  order, from the  most-sigfinicant bits to the least-significant bits."
+	 *
+	 * so the order of the components is intentionally not flipped between the pixel
+	 * format and the DRM format.
+	 */
+	case HAL_PIXEL_FORMAT_RGB_565:
+		return DRM_FORMAT_RGB565;
+	case HAL_PIXEL_FORMAT_BGRA_8888:
+		return DRM_FORMAT_ARGB8888;
+	case HAL_PIXEL_FORMAT_RAW16:
+		return DRM_FORMAT_R16;
 	/*
 	 * 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
@@ -41,17 +51,97 @@
 	 */
 	case HAL_PIXEL_FORMAT_BLOB:
 		return DRM_FORMAT_R8;
-#if ANDROID_VERSION >= 0x0a00
-	case HAL_PIXEL_FORMAT_RGBA_1010102:
-		return DRM_FORMAT_ABGR2101010;
+	case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+		return DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED;
+	case HAL_PIXEL_FORMAT_YCbCr_420_888:
+		return DRM_FORMAT_FLEX_YCbCr_420_888;
+	case HAL_PIXEL_FORMAT_Y8:
+		return DRM_FORMAT_R8;
+	case HAL_PIXEL_FORMAT_Y16:
+		return DRM_FORMAT_R16;
+	case HAL_PIXEL_FORMAT_YV12:
+		return DRM_FORMAT_YVU420_ANDROID;
+#if ANDROID_API_LEVEL >= 29
 	case HAL_PIXEL_FORMAT_RGBA_FP16:
 		return DRM_FORMAT_ABGR16161616F;
+	case HAL_PIXEL_FORMAT_RGBA_1010102:
+		return DRM_FORMAT_ABGR2101010;
+#endif
+#if ANDROID_API_LEVEL >= 30
+	case HAL_PIXEL_FORMAT_YCBCR_P010:
+		return DRM_FORMAT_P010;
 #endif
 	}
 
 	return DRM_FORMAT_NONE;
 }
 
+static inline void handle_usage(uint64_t *gralloc_usage, uint64_t gralloc_mask,
+				uint64_t *bo_use_flags, uint64_t bo_mask)
+{
+	if ((*gralloc_usage) & gralloc_mask) {
+		(*gralloc_usage) &= ~gralloc_mask;
+		(*bo_use_flags) |= bo_mask;
+	}
+}
+
+uint64_t cros_gralloc_convert_usage(uint64_t usage)
+{
+	uint64_t use_flags = BO_USE_NONE;
+
+	/*
+	 * GRALLOC_USAGE_SW_READ_OFTEN contains GRALLOC_USAGE_SW_READ_RARELY, thus OFTEN must be
+	 * handled first. The same applies to GRALLOC_USAGE_SW_WRITE_OFTEN.
+	 */
+	handle_usage(&usage, GRALLOC_USAGE_SW_READ_OFTEN, &use_flags, BO_USE_SW_READ_OFTEN);
+	handle_usage(&usage, GRALLOC_USAGE_SW_READ_RARELY, &use_flags, BO_USE_SW_READ_RARELY);
+	handle_usage(&usage, GRALLOC_USAGE_SW_WRITE_OFTEN, &use_flags, BO_USE_SW_WRITE_OFTEN);
+	handle_usage(&usage, GRALLOC_USAGE_SW_WRITE_RARELY, &use_flags, BO_USE_SW_WRITE_RARELY);
+	handle_usage(&usage, GRALLOC_USAGE_HW_TEXTURE, &use_flags, BO_USE_TEXTURE);
+	handle_usage(&usage, GRALLOC_USAGE_HW_RENDER, &use_flags, BO_USE_RENDERING);
+	handle_usage(&usage, GRALLOC_USAGE_HW_2D, &use_flags, BO_USE_RENDERING);
+	/* HWC wants to use display hardware, but can defer to OpenGL. */
+	handle_usage(&usage, GRALLOC_USAGE_HW_COMPOSER, &use_flags,
+		     BO_USE_SCANOUT | BO_USE_TEXTURE);
+	handle_usage(&usage, GRALLOC_USAGE_HW_FB, &use_flags, BO_USE_NONE);
+	/*
+	 * This flag potentially covers external display for the normal drivers (i915/rockchip) and
+	 * usb monitors (evdi/udl). It's complicated so ignore it.
+	 */
+	handle_usage(&usage, GRALLOC_USAGE_EXTERNAL_DISP, &use_flags, BO_USE_NONE);
+	/* Map PROTECTED to linear until real HW protection is available on Android. */
+	handle_usage(&usage, GRALLOC_USAGE_PROTECTED, &use_flags, BO_USE_LINEAR);
+	handle_usage(&usage, GRALLOC_USAGE_CURSOR, &use_flags, BO_USE_NONE);
+	/* HACK: See b/30054495 for BO_USE_SW_READ_OFTEN. */
+	handle_usage(&usage, GRALLOC_USAGE_HW_VIDEO_ENCODER, &use_flags,
+		     BO_USE_HW_VIDEO_ENCODER | BO_USE_SW_READ_OFTEN);
+	handle_usage(&usage, GRALLOC_USAGE_HW_CAMERA_WRITE, &use_flags, BO_USE_CAMERA_WRITE);
+	handle_usage(&usage, GRALLOC_USAGE_HW_CAMERA_READ, &use_flags, BO_USE_CAMERA_READ);
+	handle_usage(&usage, GRALLOC_USAGE_RENDERSCRIPT, &use_flags, BO_USE_RENDERSCRIPT);
+	handle_usage(&usage, BUFFER_USAGE_VIDEO_DECODER, &use_flags, BO_USE_HW_VIDEO_DECODER);
+	handle_usage(&usage, BUFFER_USAGE_GPU_DATA_BUFFER, &use_flags, BO_USE_GPU_DATA_BUFFER);
+	handle_usage(&usage, BUFFER_USAGE_FRONT_RENDERING, &use_flags, BO_USE_FRONT_RENDERING);
+
+	if (usage) {
+		drv_log("Unhandled gralloc usage: %llx\n", (unsigned long long)usage);
+		return BO_USE_NONE;
+	}
+
+	return use_flags;
+}
+
+uint32_t cros_gralloc_convert_map_usage(uint64_t usage)
+{
+	uint32_t map_flags = BO_MAP_NONE;
+
+	if (usage & GRALLOC_USAGE_SW_READ_MASK)
+		map_flags |= BO_MAP_READ;
+	if (usage & GRALLOC_USAGE_SW_WRITE_MASK)
+		map_flags |= BO_MAP_WRITE;
+
+	return map_flags;
+}
+
 cros_gralloc_handle_t cros_gralloc_convert_handle(buffer_handle_t handle)
 {
 	auto hnd = reinterpret_cast<cros_gralloc_handle_t>(handle);
diff --git a/cros_gralloc/cros_gralloc_helpers.h b/cros_gralloc/cros_gralloc_helpers.h
index a43833d..312d2f7 100644
--- a/cros_gralloc/cros_gralloc_helpers.h
+++ b/cros_gralloc/cros_gralloc_helpers.h
@@ -9,17 +9,38 @@
 
 #include "../drv.h"
 #include "cros_gralloc_handle.h"
-#include "cros_gralloc_types.h"
 
 #include <system/graphics.h>
 #include <system/window.h>
 
+#include <string>
+
+// Reserve the GRALLOC_USAGE_PRIVATE_0 bit from hardware/gralloc.h 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 (1U << 28)
+
+struct cros_gralloc_buffer_descriptor {
+	uint32_t width;
+	uint32_t height;
+	int32_t droid_format;
+	int32_t droid_usage;
+	uint32_t drm_format;
+	uint64_t use_flags;
+	uint64_t reserved_region_size;
+	std::string name;
+};
+
 constexpr uint32_t cros_gralloc_magic = 0xABCDDCBA;
 constexpr uint32_t handle_data_size =
     ((sizeof(struct cros_gralloc_handle) - offsetof(cros_gralloc_handle, fds[0])) / sizeof(int));
 
 uint32_t cros_gralloc_convert_format(int32_t format);
 
+uint64_t cros_gralloc_convert_usage(uint64_t usage);
+
+uint32_t cros_gralloc_convert_map_usage(uint64_t usage);
+
 cros_gralloc_handle_t cros_gralloc_convert_handle(buffer_handle_t handle);
 
 int32_t cros_gralloc_sync_wait(int32_t fence, bool close_fence);
diff --git a/cros_gralloc/cros_gralloc_types.h b/cros_gralloc/cros_gralloc_types.h
deleted file mode 100644
index 22f58e2..0000000
--- a/cros_gralloc/cros_gralloc_types.h
+++ /dev/null
@@ -1,23 +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.
- */
-
-#ifndef CROS_GRALLOC_TYPES_H
-#define CROS_GRALLOC_TYPES_H
-
-#include <string>
-
-struct cros_gralloc_buffer_descriptor {
-	uint32_t width;
-	uint32_t height;
-	int32_t droid_format;
-	int32_t droid_usage;
-	uint32_t drm_format;
-	uint64_t use_flags;
-	uint64_t reserved_region_size;
-	std::string name;
-};
-
-#endif
diff --git a/cros_gralloc/gralloc0/gralloc0.cc b/cros_gralloc/gralloc0/gralloc0.cc
index 5899d5a..53c89fd 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"
 
@@ -15,7 +14,7 @@
 struct gralloc0_module {
 	gralloc_module_t base;
 	std::unique_ptr<alloc_device_t> alloc;
-	std::unique_ptr<cros_gralloc_driver> driver;
+	cros_gralloc_driver *driver;
 	bool initialized;
 	std::mutex initialization_mutex;
 };
@@ -61,84 +60,8 @@
 };
 // clang-format on
 
-// Gralloc0 doesn't define a video decoder flag. However, the IAllocator gralloc0
-// passthrough gives the low 32-bits of the BufferUsage flags to gralloc0 in their
-// 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;
-
-	if (usage & GRALLOC_USAGE_CURSOR)
-		use_flags |= BO_USE_NONE;
-	if ((usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_RARELY)
-		use_flags |= BO_USE_SW_READ_RARELY;
-	if ((usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN)
-		use_flags |= BO_USE_SW_READ_OFTEN;
-	if ((usage & GRALLOC_USAGE_SW_WRITE_MASK) == GRALLOC_USAGE_SW_WRITE_RARELY)
-		use_flags |= BO_USE_SW_WRITE_RARELY;
-	if ((usage & GRALLOC_USAGE_SW_WRITE_MASK) == GRALLOC_USAGE_SW_WRITE_OFTEN)
-		use_flags |= BO_USE_SW_WRITE_OFTEN;
-	if (usage & GRALLOC_USAGE_HW_TEXTURE)
-		use_flags |= BO_USE_TEXTURE;
-	if (usage & GRALLOC_USAGE_HW_RENDER)
-		use_flags |= BO_USE_RENDERING;
-	if (usage & GRALLOC_USAGE_HW_2D)
-		use_flags |= BO_USE_RENDERING;
-	if (usage & GRALLOC_USAGE_HW_COMPOSER)
-		/* HWC wants to use display hardware, but can defer to OpenGL. */
-		use_flags |= BO_USE_SCANOUT | BO_USE_TEXTURE;
-	if (usage & GRALLOC_USAGE_HW_FB)
-		use_flags |= BO_USE_NONE;
-	if (usage & GRALLOC_USAGE_EXTERNAL_DISP)
-		/*
-		 * This flag potentially covers external display for the normal drivers (i915,
-		 * 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;
-	if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) {
-		use_flags |= BO_USE_HW_VIDEO_ENCODER;
-		/*HACK: See b/30054495 */
-		use_flags |= BO_USE_SW_READ_OFTEN;
-	}
-	if (usage & GRALLOC_USAGE_HW_CAMERA_WRITE)
-		use_flags |= BO_USE_CAMERA_WRITE;
-	if (usage & GRALLOC_USAGE_HW_CAMERA_READ)
-		use_flags |= BO_USE_CAMERA_READ;
-	if (usage & GRALLOC_USAGE_RENDERSCRIPT)
-		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;
-}
-
-static uint32_t gralloc0_convert_map_usage(int map_usage)
-{
-	uint32_t map_flags = BO_MAP_NONE;
-
-	if (map_usage & GRALLOC_USAGE_SW_READ_MASK)
-		map_flags |= BO_MAP_READ;
-	if (map_usage & GRALLOC_USAGE_SW_WRITE_MASK)
-		map_flags |= BO_MAP_WRITE;
-
-	return map_flags;
-}
-
 static int gralloc0_droid_yuv_format(int droid_format)
 {
-
 	return (droid_format == HAL_PIXEL_FORMAT_YCbCr_420_888 ||
 		droid_format == HAL_PIXEL_FORMAT_YV12);
 }
@@ -147,7 +70,6 @@
 			  buffer_handle_t *handle, int *stride)
 {
 	int32_t ret;
-	bool supported;
 	struct cros_gralloc_buffer_descriptor descriptor;
 	auto mod = (struct gralloc0_module const *)dev->common.module;
 
@@ -156,31 +78,10 @@
 	descriptor.droid_format = format;
 	descriptor.droid_usage = usage;
 	descriptor.drm_format = cros_gralloc_convert_format(format);
-	descriptor.use_flags = gralloc0_convert_usage(usage);
+	descriptor.use_flags = cros_gralloc_convert_usage(usage);
 	descriptor.reserved_region_size = 0;
 
-	supported = mod->driver->is_supported(&descriptor);
-	if (!supported && (usage & GRALLOC_USAGE_HW_COMPOSER)) {
-		descriptor.use_flags &= ~BO_USE_SCANOUT;
-		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.
-		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);
-	}
-
-	if (!supported) {
+	if (!mod->driver->is_supported(&descriptor)) {
 		drv_log("Unsupported combination -- HAL format: %u, HAL usage: %u, "
 			"drv_format: %4.4s, use_flags: %llu\n",
 			format, usage, reinterpret_cast<char *>(&descriptor.drm_format),
@@ -217,11 +118,9 @@
 	if (mod->initialized)
 		return 0;
 
-	mod->driver = std::make_unique<cros_gralloc_driver>();
-	if (mod->driver->init()) {
-		drv_log("Failed to initialize driver.\n");
+	mod->driver = cros_gralloc_driver::get_instance();
+	if (!mod->driver)
 		return -ENODEV;
-	}
 
 	if (initialize_alloc) {
 		mod->alloc = std::make_unique<alloc_device_t>();
@@ -381,20 +280,20 @@
 		memset(info, 0, sizeof(*info));
 		info->drm_fourcc = drv_get_standard_fourcc(hnd->format);
 		info->num_fds = hnd->num_planes;
+		for (int i = 0; i < info->num_fds; i++)
+			info->fds[i] = hnd->fds[i];
+
 		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];
-			}
+		for (uint32_t i = 0; i < DRV_MAX_PLANES; i++) {
+			if (!strides[i])
+				break;
+
+			info->stride[i] = strides[i];
+			info->offset[i] = offsets[i];
 		}
 		break;
 	case GRALLOC_DRM_GET_USAGE:
@@ -453,7 +352,7 @@
 	assert(w >= 0);
 	assert(h >= 0);
 
-	map_flags = gralloc0_convert_map_usage(usage);
+	map_flags = cros_gralloc_convert_map_usage(static_cast<uint64_t>(usage));
 	ret = mod->driver->lock(handle, fence_fd, true, &rect, map_flags, addr);
 	*vaddr = addr[0];
 	return ret;
@@ -505,7 +404,7 @@
 	assert(w >= 0);
 	assert(h >= 0);
 
-	map_flags = gralloc0_convert_map_usage(usage);
+	map_flags = cros_gralloc_convert_map_usage(static_cast<uint64_t>(usage));
 	ret = mod->driver->lock(handle, fence_fd, true, &rect, map_flags, addr);
 	if (ret)
 		return ret;
diff --git a/cros_gralloc/gralloc0/tests/gralloctest.c b/cros_gralloc/gralloc0/tests/gralloctest.c
index eea36e4..9d8101c 100644
--- a/cros_gralloc/gralloc0/tests/gralloctest.c
+++ b/cros_gralloc/gralloc0/tests/gralloctest.c
@@ -262,6 +262,8 @@
 	int err;
 	hw_module_t const *hw_module;
 	struct gralloctest_context *ctx = calloc(1, sizeof(*ctx));
+	if (!ctx)
+		return NULL;
 
 	err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &hw_module);
 	if (err)
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..b779704 100644
--- a/cros_gralloc/gralloc4/Android.bp
+++ b/cros_gralloc/gralloc4/Android.bp
@@ -23,34 +23,8 @@
     default_applicable_licenses: ["external_minigbm_license"],
 }
 
-cc_defaults {
-    name: "service_minigbm_defaults",
-    relative_install_path: "hw",
-    vendor: true,
-
-    vintf_fragments: ["android.hardware.graphics.allocator@4.0.xml"],
-
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-
-    shared_libs: [
-        "android.hardware.graphics.allocator@4.0",
-        "android.hardware.graphics.mapper@4.0",
-        "libbase",
-        "libcutils",
-        "libgralloctypes",
-        "libhidlbase",
-        "liblog",
-        "libsync",
-        "libutils",
-    ],
-
-    static_libs: [
-        "libdrm",
-    ],
-
+filegroup {
+    name: "minigbm_gralloc4_allocator_files",
     srcs: [
         "CrosGralloc4Allocator.cc",
         "CrosGralloc4AllocatorService.cc",
@@ -58,73 +32,116 @@
     ],
 }
 
-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",
-    relative_install_path: "hw",
-    vendor: true,
-
-    vintf_fragments: ["android.hardware.graphics.mapper@4.0.xml"],
-
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-
-    shared_libs: [
-        "android.hardware.graphics.mapper@4.0",
-        "libbase",
-        "libcutils",
-        "libgralloctypes",
-        "libhidlbase",
-        "liblog",
-        "libsync",
-        "libutils",
-    ],
-
-    static_libs: [
-        "libdrm",
-    ],
-
+filegroup {
+    name: "minigbm_gralloc4_mapper_files",
     srcs: [
         "CrosGralloc4Mapper.cc",
         "CrosGralloc4Utils.cc",
     ],
 }
 
-cc_library_shared {
-    name: "android.hardware.graphics.mapper@4.0-impl.minigbm",
-    defaults: ["impl_minigbm_defaults"],
+cc_defaults {
+    name: "minigbm_gralloc4_common_defaults",
+    defaults: ["minigbm_cros_gralloc_defaults"],
 
-    static_libs: [
-        "libminigbm_cros_gralloc",
+    shared_libs: [
+        "android.hardware.graphics.mapper@4.0",
+        "libgralloctypes",
+        "libhidlbase",
+        "libbase",
+        "libutils",
     ],
 
+    cflags: ["-Wno-sign-compare"],
+    relative_install_path: "hw",
+}
+
+cc_defaults {
+    name: "minigbm_gralloc4_allocator_defaults",
+    defaults: ["minigbm_gralloc4_common_defaults"],
+
+    shared_libs: ["android.hardware.graphics.allocator@4.0"],
+    srcs: [":minigbm_gralloc4_allocator_files"],
+}
+
+cc_binary {
+    name: "android.hardware.graphics.allocator@4.0-service.minigbm",
+    defaults: ["minigbm_gralloc4_allocator_defaults"],
+    shared_libs: ["libminigbm_gralloc"],
+    vintf_fragments: ["android.hardware.graphics.allocator@4.0.xml"],
+    init_rc: ["android.hardware.graphics.allocator@4.0-service.minigbm.rc"],
+}
+
+cc_binary {
+    name: "android.hardware.graphics.allocator@4.0-service.minigbm_msm",
+    defaults: ["minigbm_gralloc4_allocator_defaults"],
+    shared_libs: ["libminigbm_gralloc_msm"],
+    vintf_fragments: ["android.hardware.graphics.allocator@4.0.xml"],
+    init_rc: ["android.hardware.graphics.allocator@4.0-service.minigbm_msm.rc"],
+}
+
+cc_binary {
+    name: "android.hardware.graphics.allocator@4.0-service.minigbm_arcvm",
+    defaults: ["minigbm_gralloc4_allocator_defaults"],
+    shared_libs: ["libminigbm_gralloc_arcvm"],
+    vintf_fragments: ["android.hardware.graphics.allocator@4.0.xml"],
+    init_rc: ["android.hardware.graphics.allocator@4.0-service.minigbm_arcvm.rc"],
+}
+
+cc_binary {
+    name: "android.hardware.graphics.allocator@4.0-service.minigbm_intel",
+    defaults: ["minigbm_gralloc4_allocator_defaults"],
+    shared_libs: ["libminigbm_gralloc_intel"],
+    vintf_fragments: ["android.hardware.graphics.allocator@4.0.xml"],
+    init_rc: ["android.hardware.graphics.allocator@4.0-service.minigbm_intel.rc"],
+    enabled: false,
+    arch: {
+        x86: {
+            enabled: true,
+        },
+        x86_64: {
+            enabled: true,
+        },
+    },
+}
+
+cc_library_shared {
+    name: "android.hardware.graphics.mapper@4.0-impl.minigbm",
+    defaults: ["minigbm_gralloc4_common_defaults"],
+    shared_libs: ["libminigbm_gralloc"],
+    vintf_fragments: ["android.hardware.graphics.mapper@4.0.xml"],
+    srcs: [":minigbm_gralloc4_mapper_files"],
 }
 
 cc_library_shared {
     name: "android.hardware.graphics.mapper@4.0-impl.minigbm_msm",
-    defaults: ["impl_minigbm_defaults"],
+    defaults: ["minigbm_gralloc4_common_defaults"],
+    shared_libs: ["libminigbm_gralloc_msm"],
+    vintf_fragments: ["android.hardware.graphics.mapper@4.0.xml"],
+    srcs: [":minigbm_gralloc4_mapper_files"],
+}
 
-    static_libs: [
-        "libminigbm_cros_gralloc_msm",
-    ],
+cc_library_shared {
+    name: "android.hardware.graphics.mapper@4.0-impl.minigbm_arcvm",
+    defaults: ["minigbm_gralloc4_common_defaults"],
+    shared_libs: ["libminigbm_gralloc_arcvm"],
+    vintf_fragments: ["android.hardware.graphics.mapper@4.0.xml"],
+    srcs: [":minigbm_gralloc4_mapper_files"],
+}
 
+cc_library_shared {
+    name: "android.hardware.graphics.mapper@4.0-impl.minigbm_intel",
+    defaults: ["minigbm_gralloc4_common_defaults"],
+    shared_libs: ["libminigbm_gralloc_intel"],
+    vintf_fragments: ["android.hardware.graphics.mapper@4.0.xml"],
+    srcs: [":minigbm_gralloc4_mapper_files"],
+    enabled: false,
+    arch: {
+        x86: {
+            enabled: true,
+        },
+        x86_64: {
+            enabled: true,
+        },
+    },
 }
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc b/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc
index e7e5f3a..0368e1a 100644
--- a/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc
+++ b/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc
@@ -23,11 +23,9 @@
 using BufferDescriptorInfo =
         android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo;
 
-CrosGralloc4Allocator::CrosGralloc4Allocator() : mDriver(std::make_unique<cros_gralloc_driver>()) {
-    if (mDriver->init()) {
-        drv_log("Failed to initialize driver.\n");
-        mDriver = nullptr;
-    }
+Error CrosGralloc4Allocator::init() {
+    mDriver = cros_gralloc_driver::get_instance();
+    return mDriver ? Error::NONE : Error::NO_RESOURCES;
 }
 
 Error CrosGralloc4Allocator::allocate(const BufferDescriptorInfo& descriptor, uint32_t* outStride,
@@ -46,13 +44,7 @@
         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) {
+    if (!mDriver->is_supported(&crosDescriptor)) {
         std::string drmFormatString = get_drm_format_string(crosDescriptor.drm_format);
         std::string pixelFormatString = getPixelFormatString(descriptor.format);
         std::string usageString = getUsageString(descriptor.usage);
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Allocator.h b/cros_gralloc/gralloc4/CrosGralloc4Allocator.h
index 21ad7ad..1555a61 100644
--- a/cros_gralloc/gralloc4/CrosGralloc4Allocator.h
+++ b/cros_gralloc/gralloc4/CrosGralloc4Allocator.h
@@ -11,16 +11,18 @@
 
 class CrosGralloc4Allocator : public android::hardware::graphics::allocator::V4_0::IAllocator {
   public:
-    CrosGralloc4Allocator();
+    CrosGralloc4Allocator() = default;
 
     android::hardware::Return<void> allocate(const android::hardware::hidl_vec<uint8_t>& descriptor,
                                              uint32_t count, allocate_cb hidl_cb) override;
 
+    android::hardware::graphics::mapper::V4_0::Error init();
+
   private:
     android::hardware::graphics::mapper::V4_0::Error allocate(
             const android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo&
                     description,
             uint32_t* outStride, android::hardware::hidl_handle* outHandle);
 
-    std::unique_ptr<cros_gralloc_driver> mDriver;
+    cros_gralloc_driver* mDriver = nullptr;
 };
diff --git a/cros_gralloc/gralloc4/CrosGralloc4AllocatorService.cc b/cros_gralloc/gralloc4/CrosGralloc4AllocatorService.cc
index 5b79860..99bc92e 100644
--- a/cros_gralloc/gralloc4/CrosGralloc4AllocatorService.cc
+++ b/cros_gralloc/gralloc4/CrosGralloc4AllocatorService.cc
@@ -13,18 +13,23 @@
 using android::sp;
 using android::hardware::configureRpcThreadpool;
 using android::hardware::joinRpcThreadpool;
-using android::hardware::graphics::allocator::V4_0::IAllocator;
+using android::hardware::graphics::mapper::V4_0::Error;
 
 int main(int, char**) {
-    sp<IAllocator> allocator = new CrosGralloc4Allocator();
-    configureRpcThreadpool(4, true /* callerWillJoin */);
-    if (allocator->registerAsService() != android::NO_ERROR) {
-        ALOGE("failed to register graphics IAllocator 4.0 service");
+    sp<CrosGralloc4Allocator> allocator = new CrosGralloc4Allocator();
+    if (allocator->init() != Error::NONE) {
+        ALOGE("Failed to initialize IAllocator 4.0 service.");
         return -EINVAL;
     }
 
-    ALOGI("graphics IAllocator 4.0 service is initialized");
+    configureRpcThreadpool(4, true /* callerWillJoin */);
+    if (allocator->registerAsService() != android::NO_ERROR) {
+        ALOGE("Failed to register graphics IAllocator 4.0 service.");
+        return -EINVAL;
+    }
+
+    ALOGI("IAllocator 4.0 service is initialized.");
     android::hardware::joinRpcThreadpool();
-    ALOGI("graphics IAllocator 4.0 service is terminating");
+    ALOGI("IAllocator 4.0 service is terminating.");
     return 0;
 }
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc b/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc
index 1bfd442..8f952e1 100644
--- a/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc
+++ b/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc
@@ -16,8 +16,6 @@
 #include "cros_gralloc/cros_gralloc_helpers.h"
 #include "cros_gralloc/gralloc4/CrosGralloc4Utils.h"
 
-#include "helpers.h"
-
 using aidl::android::hardware::graphics::common::BlendMode;
 using aidl::android::hardware::graphics::common::Dataspace;
 using aidl::android::hardware::graphics::common::PlaneLayout;
@@ -31,62 +29,6 @@
 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;
-    }
-
-    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,
                                                   createDescriptor_cb hidlCb) {
     hidl_vec<uint8_t> descriptor;
@@ -448,13 +390,7 @@
         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);
+    hidlCb(Error::NONE, mDriver->is_supported(&crosDescriptor));
     return Void();
 }
 
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Mapper.h b/cros_gralloc/gralloc4/CrosGralloc4Mapper.h
index 3c159a2..0641b29 100644
--- a/cros_gralloc/gralloc4/CrosGralloc4Mapper.h
+++ b/cros_gralloc/gralloc4/CrosGralloc4Mapper.h
@@ -11,8 +11,7 @@
 
 class CrosGralloc4Mapper : public android::hardware::graphics::mapper::V4_0::IMapper {
   public:
-    CrosGralloc4Mapper();
-    ~CrosGralloc4Mapper();
+    CrosGralloc4Mapper() = default;
 
     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;
+    cros_gralloc_driver* mDriver = cros_gralloc_driver::get_instance();
 };
 
 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..63ec8af 100644
--- a/cros_gralloc/gralloc4/CrosGralloc4Utils.cc
+++ b/cros_gralloc/gralloc4/CrosGralloc4Utils.cc
@@ -30,283 +30,28 @@
         android::hardware::graphics::mapper::V4_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));
+    return android::hardware::graphics::common::V1_2::toString(format);
 }
 
 std::string getUsageString(hidl_bitfield<BufferUsage> bufferUsage) {
-    using Underlying = typename std::underlying_type<BufferUsage>::type;
+    static_assert(std::is_same<std::underlying_type<BufferUsage>::type, uint64_t>::value);
 
-    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, '|');
+    const uint64_t usage = static_cast<uint64_t>(bufferUsage);
+    return android::hardware::graphics::common::V1_2::toString<BufferUsage>(usage);
 }
 
 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;
+    static_assert(std::is_same<std::underlying_type<PixelFormat>::type, int32_t>::value);
+
+    const uint32_t drmFormat = cros_gralloc_convert_format(static_cast<int32_t>(format));
+    if (drmFormat == DRM_FORMAT_NONE) return -EINVAL;
+
+    *outDrmFormat = drmFormat;
+    return 0;
 }
 
 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;
+    *outBufferUsage = cros_gralloc_convert_usage(grallocUsage);
     return 0;
 }
 
@@ -337,16 +82,7 @@
 }
 
 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;
+    *outMapUsage = cros_gralloc_convert_map_usage(grallocUsage);
     return 0;
 }
 
@@ -547,13 +283,13 @@
 
                     {DRM_FORMAT_RGB565,
                      {{
-                             .components = {{.type = android::gralloc4::PlaneLayoutComponentType_R,
+                             .components = {{.type = android::gralloc4::PlaneLayoutComponentType_B,
                                              .offsetInBits = 0,
                                              .sizeInBits = 5},
                                             {.type = android::gralloc4::PlaneLayoutComponentType_G,
                                              .offsetInBits = 5,
                                              .sizeInBits = 6},
-                                            {.type = android::gralloc4::PlaneLayoutComponentType_B,
+                                            {.type = android::gralloc4::PlaneLayoutComponentType_R,
                                              .offsetInBits = 11,
                                              .sizeInBits = 5}},
                              .sampleIncrementInBits = 16,
@@ -561,7 +297,7 @@
                              .verticalSubsampling = 1,
                      }}},
 
-                    {DRM_FORMAT_RGB888,
+                    {DRM_FORMAT_BGR888,
                      {{
                              .components = {{.type = android::gralloc4::PlaneLayoutComponentType_R,
                                              .offsetInBits = 0,
diff --git a/cros_gralloc/gralloc4/CrosGralloc4Utils.h b/cros_gralloc/gralloc4/CrosGralloc4Utils.h
index 370922c..fa096ef 100644
--- a/cros_gralloc/gralloc4/CrosGralloc4Utils.h
+++ b/cros_gralloc/gralloc4/CrosGralloc4Utils.h
@@ -11,7 +11,7 @@
 #include <android/hardware/graphics/common/1.2/types.h>
 #include <android/hardware/graphics/mapper/4.0/IMapper.h>
 
-#include "cros_gralloc/cros_gralloc_types.h"
+struct cros_gralloc_buffer_descriptor;
 
 std::string getPixelFormatString(android::hardware::graphics::common::V1_2::PixelFormat format);
 
diff --git a/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm.rc b/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm.rc
index a96a6e1..4f8680b 100644
--- a/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm.rc
+++ b/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm.rc
@@ -21,4 +21,4 @@
     group graphics drmrpc
     capabilities SYS_NICE
     onrestart restart surfaceflinger
-    writepid /dev/cpuset/system-background/tasks
+    task_profiles ServiceCapacityLow
diff --git a/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm_arcvm.rc b/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm_arcvm.rc
new file mode 100644
index 0000000..4e8818a
--- /dev/null
+++ b/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm_arcvm.rc
@@ -0,0 +1,24 @@
+#
+# Copyright 2021 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_arcvm
+    interface android.hardware.graphics.allocator@4.0::IAllocator default
+    class hal animation
+    user system
+    group graphics drmrpc
+    capabilities SYS_NICE
+    onrestart restart surfaceflinger
+    task_profiles ServiceCapacityLow
diff --git a/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm_intel.rc b/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm_intel.rc
new file mode 100644
index 0000000..9a3512f
--- /dev/null
+++ b/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm_intel.rc
@@ -0,0 +1,24 @@
+#
+# 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_intel
+    interface android.hardware.graphics.allocator@4.0::IAllocator default
+    class hal animation
+    user system
+    group graphics drmrpc
+    capabilities SYS_NICE
+    onrestart restart surfaceflinger
+    task_profiles ServiceCapacityLow
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
index dceb747..8ecc94b 100644
--- 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
@@ -21,4 +21,4 @@
     group graphics drmrpc
     capabilities SYS_NICE
     onrestart restart surfaceflinger
-    writepid /dev/cpuset/system-background/tasks
+    task_profiles ServiceCapacityLow
diff --git a/dri.c b/dri.c
index 13d4833..4ee133d 100644
--- a/dri.c
+++ b/dri.c
@@ -18,8 +18,8 @@
 #include <xf86drm.h>
 
 #include "dri.h"
+#include "drv_helpers.h"
 #include "drv_priv.h"
-#include "helpers.h"
 #include "util.h"
 
 static const struct {
@@ -196,8 +196,12 @@
 	const __DRIextension *loader_extensions[] = { NULL };
 
 	struct dri_driver *dri = drv->priv;
+	char *node_name = drmGetRenderDeviceNameFromFd(drv_get_fd(drv));
+	if (!node_name)
+		return -ENODEV;
 
-	dri->fd = open(drmGetRenderDeviceNameFromFd(drv_get_fd(drv)), O_RDWR);
+	dri->fd = open(node_name, O_RDWR);
+	free(node_name);
 	if (dri->fd < 0)
 		return -ENODEV;
 
@@ -385,13 +389,20 @@
 	return 0;
 }
 
-int dri_bo_destroy(struct bo *bo)
+int dri_bo_release(struct bo *bo)
 {
 	struct dri_driver *dri = bo->drv->priv;
 
 	assert(bo->priv);
-	close_gem_handle(bo->handles[0].u32, bo->drv->fd);
 	dri->image_extension->destroyImage(bo->priv);
+	/* Not clearing bo->priv as we still use it to determine which destroy to call. */
+	return 0;
+}
+
+int dri_bo_destroy(struct bo *bo)
+{
+	assert(bo->priv);
+	close_gem_handle(bo->handles[0].u32, bo->drv->fd);
 	bo->priv = NULL;
 	return 0;
 }
@@ -449,11 +460,22 @@
 
 	uint64_t planes;
 	GLboolean ret = dri->image_extension->queryDmaBufFormatModifierAttribs(
-	    dri->device, format, modifier, __DRI_IMAGE_ATTRIB_NUM_PLANES, &planes);
+	    dri->device, format, modifier, __DRI_IMAGE_FORMAT_MODIFIER_ATTRIB_PLANE_COUNT, &planes);
 	if (!ret)
 		return 0;
 
 	return planes;
 }
 
+bool dri_query_modifiers(struct driver *drv, uint32_t format, int max, uint64_t *modifiers,
+			 int *count)
+{
+	struct dri_driver *dri = drv->priv;
+	if (!dri->image_extension->queryDmaBufModifiers)
+		return false;
+
+	return dri->image_extension->queryDmaBufModifiers(dri->device, format, max, modifiers, NULL,
+							  count);
+}
+
 #endif
diff --git a/dri.h b/dri.h
index 6218e82..daadf30 100644
--- a/dri.h
+++ b/dri.h
@@ -33,9 +33,12 @@
 int dri_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
 				 const uint64_t *modifiers, uint32_t modifier_count);
 int dri_bo_import(struct bo *bo, struct drv_import_fd_data *data);
+int dri_bo_release(struct bo *bo);
 int dri_bo_destroy(struct bo *bo);
 void *dri_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags);
 int dri_bo_unmap(struct bo *bo, struct vma *vma);
 size_t dri_num_planes_from_modifier(struct driver *drv, uint32_t format, uint64_t modifier);
 
+bool dri_query_modifiers(struct driver *drv, uint32_t format, int max, uint64_t *modifiers,
+			 int *count);
 #endif
diff --git a/drv.c b/drv.c
index 9b43e9f..ada02ba 100644
--- a/drv.c
+++ b/drv.c
@@ -9,7 +9,6 @@
 #include <pthread.h>
 #include <stdint.h>
 #include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 #include <sys/mman.h>
 #include <sys/types.h>
@@ -21,16 +20,13 @@
 #include <libgen.h>
 #endif
 
+#include "drv_helpers.h"
 #include "drv_priv.h"
-#include "helpers.h"
 #include "util.h"
 
 #ifdef DRV_AMDGPU
 extern const struct backend backend_amdgpu;
 #endif
-#ifdef DRV_EXYNOS
-extern const struct backend backend_exynos;
-#endif
 #ifdef DRV_I915
 extern const struct backend backend_i915;
 #endif
@@ -73,9 +69,6 @@
 #ifdef DRV_AMDGPU
 		&backend_amdgpu,
 #endif
-#ifdef DRV_EXYNOS
-		&backend_exynos,
-#endif
 #ifdef DRV_I915
 		&backend_i915,
 #endif
@@ -128,16 +121,19 @@
 	if (!drv->backend)
 		goto free_driver;
 
-	if (pthread_mutex_init(&drv->driver_lock, NULL))
+	if (pthread_mutex_init(&drv->buffer_table_lock, NULL))
 		goto free_driver;
 
 	drv->buffer_table = drmHashCreate();
 	if (!drv->buffer_table)
-		goto free_lock;
+		goto free_buffer_table_lock;
+
+	if (pthread_mutex_init(&drv->mappings_lock, NULL))
+		goto free_buffer_table;
 
 	drv->mappings = drv_array_init(sizeof(struct mapping));
 	if (!drv->mappings)
-		goto free_buffer_table;
+		goto free_mappings_lock;
 
 	drv->combos = drv_array_init(sizeof(struct combination));
 	if (!drv->combos)
@@ -155,10 +151,12 @@
 
 free_mappings:
 	drv_array_destroy(drv->mappings);
+free_mappings_lock:
+	pthread_mutex_destroy(&drv->mappings_lock);
 free_buffer_table:
 	drmHashDestroy(drv->buffer_table);
-free_lock:
-	pthread_mutex_destroy(&drv->driver_lock);
+free_buffer_table_lock:
+	pthread_mutex_destroy(&drv->buffer_table_lock);
 free_driver:
 	free(drv);
 	return NULL;
@@ -166,17 +164,16 @@
 
 void drv_destroy(struct driver *drv)
 {
-	pthread_mutex_lock(&drv->driver_lock);
-
 	if (drv->backend->close)
 		drv->backend->close(drv);
 
-	drmHashDestroy(drv->buffer_table);
-	drv_array_destroy(drv->mappings);
 	drv_array_destroy(drv->combos);
 
-	pthread_mutex_unlock(&drv->driver_lock);
-	pthread_mutex_destroy(&drv->driver_lock);
+	drv_array_destroy(drv->mappings);
+	pthread_mutex_destroy(&drv->mappings_lock);
+
+	drmHashDestroy(drv->buffer_table);
+	pthread_mutex_destroy(&drv->buffer_table_lock);
 
 	free(drv);
 }
@@ -230,17 +227,111 @@
 
 	if (!bo->meta.num_planes) {
 		free(bo);
+		errno = EINVAL;
 		return NULL;
 	}
 
 	return bo;
 }
 
+static void drv_bo_mapping_destroy(struct bo *bo)
+{
+	struct driver *drv = bo->drv;
+	uint32_t idx = 0;
+
+	/*
+	 * This function is called right before the buffer is destroyed. It will free any mappings
+	 * associated with the buffer.
+	 */
+	pthread_mutex_lock(&drv->mappings_lock);
+	for (size_t plane = 0; plane < bo->meta.num_planes; plane++) {
+		while (idx < drv_array_size(drv->mappings)) {
+			struct mapping *mapping =
+			    (struct mapping *)drv_array_at_idx(drv->mappings, idx);
+			if (mapping->vma->handle != bo->handles[plane].u32) {
+				idx++;
+				continue;
+			}
+
+			if (!--mapping->vma->refcount) {
+				int ret = drv->backend->bo_unmap(bo, mapping->vma);
+				if (ret) {
+					pthread_mutex_unlock(&drv->mappings_lock);
+					assert(ret);
+					drv_log("munmap failed\n");
+					return;
+				}
+
+				free(mapping->vma);
+			}
+
+			/* This shrinks and shifts the array, so don't increment idx. */
+			drv_array_remove(drv->mappings, idx);
+		}
+	}
+	pthread_mutex_unlock(&drv->mappings_lock);
+}
+
+/*
+ * Acquire a reference on plane buffers of the bo.
+ */
+static void drv_bo_acquire(struct bo *bo)
+{
+	struct driver *drv = bo->drv;
+
+	pthread_mutex_lock(&drv->buffer_table_lock);
+	for (size_t plane = 0; plane < bo->meta.num_planes; plane++) {
+		uintptr_t num = 0;
+
+		if (!drmHashLookup(drv->buffer_table, bo->handles[plane].u32, (void **)&num))
+			drmHashDelete(drv->buffer_table, bo->handles[plane].u32);
+
+		drmHashInsert(drv->buffer_table, bo->handles[plane].u32, (void *)(num + 1));
+	}
+	pthread_mutex_unlock(&drv->buffer_table_lock);
+}
+
+/*
+ * Release a reference on plane buffers of the bo. Return true when the bo has lost all its
+ * references. Otherwise, return false.
+ */
+static bool drv_bo_release(struct bo *bo)
+{
+	struct driver *drv = bo->drv;
+	uintptr_t num;
+
+	if (drv->backend->bo_release)
+		drv->backend->bo_release(bo);
+
+	pthread_mutex_lock(&drv->buffer_table_lock);
+	for (size_t plane = 0; plane < bo->meta.num_planes; plane++) {
+		if (!drmHashLookup(drv->buffer_table, bo->handles[plane].u32, (void **)&num)) {
+			drmHashDelete(drv->buffer_table, bo->handles[plane].u32);
+
+			if (num > 1) {
+				drmHashInsert(drv->buffer_table, bo->handles[plane].u32,
+					      (void *)(num - 1));
+			}
+		}
+	}
+
+	/* The same buffer can back multiple planes with different offsets. */
+	for (size_t plane = 0; plane < bo->meta.num_planes; plane++) {
+		if (!drmHashLookup(drv->buffer_table, bo->handles[plane].u32, (void **)&num)) {
+			/* num is positive if found in the hashmap. */
+			pthread_mutex_unlock(&drv->buffer_table_lock);
+			return false;
+		}
+	}
+	pthread_mutex_unlock(&drv->buffer_table_lock);
+
+	return true;
+}
+
 struct bo *drv_bo_create(struct driver *drv, uint32_t width, uint32_t height, uint32_t format,
 			 uint64_t use_flags)
 {
 	int ret;
-	size_t plane;
 	struct bo *bo;
 	bool is_test_alloc;
 
@@ -263,20 +354,12 @@
 	}
 
 	if (ret) {
+		errno = -ret;
 		free(bo);
 		return NULL;
 	}
 
-	pthread_mutex_lock(&drv->driver_lock);
-
-	for (plane = 0; plane < bo->meta.num_planes; plane++) {
-		if (plane > 0)
-			assert(bo->meta.offsets[plane] >= bo->meta.offsets[plane - 1]);
-
-		drv_increment_reference_count(drv, bo, plane);
-	}
-
-	pthread_mutex_unlock(&drv->driver_lock);
+	drv_bo_acquire(bo);
 
 	return bo;
 }
@@ -285,7 +368,6 @@
 					uint32_t format, const uint64_t *modifiers, uint32_t count)
 {
 	int ret;
-	size_t plane;
 	struct bo *bo;
 
 	if (!drv->backend->bo_create_with_modifiers && !drv->backend->bo_compute_metadata) {
@@ -314,43 +396,16 @@
 		return NULL;
 	}
 
-	pthread_mutex_lock(&drv->driver_lock);
-
-	for (plane = 0; plane < bo->meta.num_planes; plane++) {
-		if (plane > 0)
-			assert(bo->meta.offsets[plane] >= bo->meta.offsets[plane - 1]);
-
-		drv_increment_reference_count(drv, bo, plane);
-	}
-
-	pthread_mutex_unlock(&drv->driver_lock);
+	drv_bo_acquire(bo);
 
 	return bo;
 }
 
 void drv_bo_destroy(struct bo *bo)
 {
-	int ret;
-	size_t plane;
-	uintptr_t total = 0;
-	struct driver *drv = bo->drv;
-
-	if (!bo->is_test_buffer) {
-		pthread_mutex_lock(&drv->driver_lock);
-
-		for (plane = 0; plane < bo->meta.num_planes; plane++)
-			drv_decrement_reference_count(drv, bo, plane);
-
-		for (plane = 0; plane < bo->meta.num_planes; plane++)
-			total += drv_get_reference_count(drv, bo, plane);
-
-		pthread_mutex_unlock(&drv->driver_lock);
-
-		if (total == 0) {
-			ret = drv_mapping_destroy(bo);
-			assert(ret == 0);
-			bo->drv->backend->bo_destroy(bo);
-		}
+	if (!bo->is_test_buffer && drv_bo_release(bo)) {
+		drv_bo_mapping_destroy(bo);
+		bo->drv->backend->bo_destroy(bo);
 	}
 
 	free(bo);
@@ -374,11 +429,7 @@
 		return NULL;
 	}
 
-	for (plane = 0; plane < bo->meta.num_planes; plane++) {
-		pthread_mutex_lock(&bo->drv->driver_lock);
-		drv_increment_reference_count(bo->drv, bo, plane);
-		pthread_mutex_unlock(&bo->drv->driver_lock);
-	}
+	drv_bo_acquire(bo);
 
 	bo->meta.format_modifier = data->format_modifier;
 	for (plane = 0; plane < bo->meta.num_planes; plane++) {
@@ -415,6 +466,7 @@
 void *drv_bo_map(struct bo *bo, const struct rectangle *rect, uint32_t map_flags,
 		 struct mapping **map_data, size_t plane)
 {
+	struct driver *drv = bo->drv;
 	uint32_t i;
 	uint8_t *addr;
 	struct mapping mapping = { 0 };
@@ -433,10 +485,10 @@
 	mapping.rect = *rect;
 	mapping.refcount = 1;
 
-	pthread_mutex_lock(&bo->drv->driver_lock);
+	pthread_mutex_lock(&drv->mappings_lock);
 
-	for (i = 0; i < drv_array_size(bo->drv->mappings); i++) {
-		struct mapping *prior = (struct mapping *)drv_array_at_idx(bo->drv->mappings, i);
+	for (i = 0; i < drv_array_size(drv->mappings); i++) {
+		struct mapping *prior = (struct mapping *)drv_array_at_idx(drv->mappings, i);
 		if (prior->vma->handle != bo->handles[plane].u32 ||
 		    prior->vma->map_flags != map_flags)
 			continue;
@@ -450,8 +502,8 @@
 		goto exact_match;
 	}
 
-	for (i = 0; i < drv_array_size(bo->drv->mappings); i++) {
-		struct mapping *prior = (struct mapping *)drv_array_at_idx(bo->drv->mappings, i);
+	for (i = 0; i < drv_array_size(drv->mappings); i++) {
+		struct mapping *prior = (struct mapping *)drv_array_at_idx(drv->mappings, i);
 		if (prior->vma->handle != bo->handles[plane].u32 ||
 		    prior->vma->map_flags != map_flags)
 			continue;
@@ -462,12 +514,18 @@
 	}
 
 	mapping.vma = calloc(1, sizeof(*mapping.vma));
+	if (!mapping.vma) {
+		*map_data = NULL;
+		pthread_mutex_unlock(&drv->mappings_lock);
+		return MAP_FAILED;
+	}
+
 	memcpy(mapping.vma->map_strides, bo->meta.strides, sizeof(mapping.vma->map_strides));
-	addr = bo->drv->backend->bo_map(bo, mapping.vma, plane, map_flags);
+	addr = drv->backend->bo_map(bo, mapping.vma, plane, map_flags);
 	if (addr == MAP_FAILED) {
 		*map_data = NULL;
 		free(mapping.vma);
-		pthread_mutex_unlock(&bo->drv->driver_lock);
+		pthread_mutex_unlock(&drv->mappings_lock);
 		return MAP_FAILED;
 	}
 
@@ -477,39 +535,40 @@
 	mapping.vma->map_flags = map_flags;
 
 success:
-	*map_data = drv_array_append(bo->drv->mappings, &mapping);
+	*map_data = drv_array_append(drv->mappings, &mapping);
 exact_match:
 	drv_bo_invalidate(bo, *map_data);
 	addr = (uint8_t *)((*map_data)->vma->addr);
 	addr += drv_bo_get_plane_offset(bo, plane);
-	pthread_mutex_unlock(&bo->drv->driver_lock);
+	pthread_mutex_unlock(&drv->mappings_lock);
 	return (void *)addr;
 }
 
 int drv_bo_unmap(struct bo *bo, struct mapping *mapping)
 {
+	struct driver *drv = bo->drv;
 	uint32_t i;
 	int ret = 0;
 
-	pthread_mutex_lock(&bo->drv->driver_lock);
+	pthread_mutex_lock(&drv->mappings_lock);
 
 	if (--mapping->refcount)
 		goto out;
 
 	if (!--mapping->vma->refcount) {
-		ret = bo->drv->backend->bo_unmap(bo, mapping->vma);
+		ret = drv->backend->bo_unmap(bo, mapping->vma);
 		free(mapping->vma);
 	}
 
-	for (i = 0; i < drv_array_size(bo->drv->mappings); i++) {
-		if (mapping == (struct mapping *)drv_array_at_idx(bo->drv->mappings, i)) {
-			drv_array_remove(bo->drv->mappings, i);
+	for (i = 0; i < drv_array_size(drv->mappings); i++) {
+		if (mapping == (struct mapping *)drv_array_at_idx(drv->mappings, i)) {
+			drv_array_remove(drv->mappings, i);
 			break;
 		}
 	}
 
 out:
-	pthread_mutex_unlock(&bo->drv->driver_lock);
+	pthread_mutex_unlock(&drv->mappings_lock);
 	return ret;
 }
 
@@ -634,17 +693,36 @@
 	return bo->meta.format;
 }
 
+uint32_t drv_bo_get_tiling(struct bo *bo)
+{
+	return bo->meta.tiling;
+}
+
+uint64_t drv_bo_get_use_flags(struct bo *bo)
+{
+	return bo->meta.use_flags;
+}
+
 size_t drv_bo_get_total_size(struct bo *bo)
 {
 	return bo->meta.total_size;
 }
 
-uint32_t drv_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags)
+/*
+ * Map internal fourcc codes back to standard fourcc codes.
+ */
+uint32_t drv_get_standard_fourcc(uint32_t fourcc_internal)
 {
-	if (drv->backend->resolve_format)
-		return drv->backend->resolve_format(drv, format, use_flags);
+	return (fourcc_internal == DRM_FORMAT_YVU420_ANDROID) ? DRM_FORMAT_YVU420 : fourcc_internal;
+}
 
-	return format;
+void drv_resolve_format_and_use_flags(struct driver *drv, uint32_t format, uint64_t use_flags,
+				      uint32_t *out_format, uint64_t *out_use_flags)
+{
+	assert(drv->backend->resolve_format_and_use_flags);
+
+	drv->backend->resolve_format_and_use_flags(drv, format, use_flags, out_format,
+						   out_use_flags);
 }
 
 uint32_t drv_num_buffers_per_bo(struct bo *bo)
@@ -696,3 +774,11 @@
 
 	return 0;
 }
+
+uint32_t drv_get_max_texture_2d_size(struct driver *drv)
+{
+	if (drv->backend->get_max_texture_2d_size)
+		return drv->backend->get_max_texture_2d_size(drv);
+
+	return UINT32_MAX;
+}
diff --git a/drv.h b/drv.h
index 4689558..3dffdff 100644
--- a/drv.h
+++ b/drv.h
@@ -14,6 +14,7 @@
 #include <drm_fourcc.h>
 #include <stdbool.h>
 #include <stdint.h>
+#include <stdlib.h>
 
 #define DRV_MAX_PLANES 4
 
@@ -39,6 +40,7 @@
 #define BO_USE_TEST_ALLOC		(1ull << 15)
 #define BO_USE_FRONT_RENDERING		(1ull << 16)
 #define BO_USE_RENDERSCRIPT		(1ull << 17)
+#define BO_USE_GPU_DATA_BUFFER		(1ull << 18)
 
 /* Quirks for allocating a buffer. */
 #define BO_QUIRK_NONE			0
@@ -69,6 +71,11 @@
 #define DRM_FORMAT_P010 fourcc_code('P', '0', '1', '0')
 #endif
 
+//TODO: remove this defination once drm_fourcc.h contains it.
+#ifndef I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS
+#define I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS fourcc_mod_code(INTEL, 6)
+#endif
+
 // clang-format on
 struct driver;
 struct bo;
@@ -171,11 +178,22 @@
 
 uint32_t drv_bo_get_format(struct bo *bo);
 
+uint32_t drv_bo_get_tiling(struct bo *bo);
+
+uint64_t drv_bo_get_use_flags(struct bo *bo);
+
+size_t drv_bo_get_total_size(struct bo *bo);
+
+uint32_t drv_get_standard_fourcc(uint32_t fourcc_internal);
+
 uint32_t drv_bytes_per_pixel_from_format(uint32_t format, size_t plane);
 
 uint32_t drv_stride_from_format(uint32_t format, uint32_t width, size_t plane);
 
-uint32_t drv_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags);
+void drv_resolve_format_and_use_flags(struct driver *drv, uint32_t format, uint64_t use_flags,
+				      uint32_t *out_format, uint64_t *out_use_flags);
+
+uint64_t drv_resolve_use_flags(struct driver *drv, uint32_t format, uint64_t use_flags);
 
 size_t drv_num_planes_from_format(uint32_t format);
 
@@ -186,6 +204,8 @@
 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 drv_get_max_texture_2d_size(struct driver *drv);
+
 #define drv_log(format, ...)                                                                       \
 	do {                                                                                       \
 		drv_log_prefix("minigbm", __FILE__, __LINE__, format, ##__VA_ARGS__);              \
diff --git a/helpers_array.c b/drv_array_helpers.c
similarity index 94%
rename from helpers_array.c
rename to drv_array_helpers.c
index 20b43e2..b4e7750 100644
--- a/helpers_array.c
+++ b/drv_array_helpers.c
@@ -3,6 +3,7 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+#include "drv_array_helpers.h"
 
 #include <assert.h>
 #include <stdint.h>
@@ -23,10 +24,17 @@
 	struct drv_array *array;
 
 	array = calloc(1, sizeof(*array));
+	if (!array)
+		return NULL;
 
 	/* Start with a power of 2 number of allocations. */
 	array->allocations = 2;
 	array->items = calloc(array->allocations, sizeof(*array->items));
+	if (!array->items) {
+		free(array);
+		return NULL;
+	}
+
 	array->item_size = item_size;
 	return array;
 }
diff --git a/helpers_array.h b/drv_array_helpers.h
similarity index 89%
rename from helpers_array.h
rename to drv_array_helpers.h
index 2893976..77544d3 100644
--- a/helpers_array.h
+++ b/drv_array_helpers.h
@@ -4,6 +4,11 @@
  * found in the LICENSE file.
  */
 
+#ifndef DRV_ARRAY_HELPERS_H
+#define DRV_ARRAY_HELPERS_H
+
+#include <stdint.h>
+
 struct drv_array;
 
 struct drv_array *drv_array_init(uint32_t item_size);
@@ -20,3 +25,5 @@
 
 /* The array and all associated data will be freed. */
 void drv_array_destroy(struct drv_array *array);
+
+#endif
diff --git a/helpers.c b/drv_helpers.c
similarity index 87%
rename from helpers.c
rename to drv_helpers.c
index a182347..6ea4b8e 100644
--- a/helpers.c
+++ b/drv_helpers.c
@@ -4,6 +4,8 @@
  * found in the LICENSE file.
  */
 
+#include "drv_helpers.h"
+
 #include <assert.h>
 #include <errno.h>
 #include <stdio.h>
@@ -15,7 +17,6 @@
 #include <xf86drm.h>
 
 #include "drv_priv.h"
-#include "helpers.h"
 #include "util.h"
 
 struct planar_layout {
@@ -483,80 +484,11 @@
 	return munmap(vma->addr, vma->length);
 }
 
-int drv_mapping_destroy(struct bo *bo)
-{
-	int ret;
-	size_t plane;
-	struct mapping *mapping;
-	uint32_t idx;
-
-	/*
-	 * This function is called right before the buffer is destroyed. It will free any mappings
-	 * associated with the buffer.
-	 */
-
-	idx = 0;
-	for (plane = 0; plane < bo->meta.num_planes; plane++) {
-		while (idx < drv_array_size(bo->drv->mappings)) {
-			mapping = (struct mapping *)drv_array_at_idx(bo->drv->mappings, idx);
-			if (mapping->vma->handle != bo->handles[plane].u32) {
-				idx++;
-				continue;
-			}
-
-			if (!--mapping->vma->refcount) {
-				ret = bo->drv->backend->bo_unmap(bo, mapping->vma);
-				if (ret) {
-					drv_log("munmap failed\n");
-					return ret;
-				}
-
-				free(mapping->vma);
-			}
-
-			/* This shrinks and shifts the array, so don't increment idx. */
-			drv_array_remove(bo->drv->mappings, idx);
-		}
-	}
-
-	return 0;
-}
-
 int drv_get_prot(uint32_t map_flags)
 {
 	return (BO_MAP_WRITE & map_flags) ? PROT_WRITE | PROT_READ : PROT_READ;
 }
 
-uintptr_t drv_get_reference_count(struct driver *drv, struct bo *bo, size_t plane)
-{
-	void *count;
-	uintptr_t num = 0;
-
-	if (!drmHashLookup(drv->buffer_table, bo->handles[plane].u32, &count))
-		num = (uintptr_t)(count);
-
-	return num;
-}
-
-void drv_increment_reference_count(struct driver *drv, struct bo *bo, size_t plane)
-{
-	uintptr_t num = drv_get_reference_count(drv, bo, plane);
-
-	/* If a value isn't in the table, drmHashDelete is a no-op */
-	drmHashDelete(drv->buffer_table, bo->handles[plane].u32);
-	drmHashInsert(drv->buffer_table, bo->handles[plane].u32, (void *)(num + 1));
-}
-
-void drv_decrement_reference_count(struct driver *drv, struct bo *bo, size_t plane)
-{
-	uintptr_t num = drv_get_reference_count(drv, bo, plane);
-
-	drmHashDelete(drv->buffer_table, bo->handles[plane].u32);
-
-	if (num > 0)
-		drmHashInsert(drv->buffer_table, bo->handles[plane].u32, (void *)(num - 1));
-}
-
 void drv_add_combination(struct driver *drv, const uint32_t format,
 			 struct format_metadata *metadata, uint64_t use_flags)
 {
@@ -641,27 +573,31 @@
 	return false;
 }
 
-/*
- * Map internal fourcc codes back to standard fourcc codes.
- */
-uint32_t drv_get_standard_fourcc(uint32_t fourcc_internal)
+void drv_resolve_format_and_use_flags_helper(struct driver *drv, uint32_t format,
+					     uint64_t use_flags, uint32_t *out_format,
+					     uint64_t *out_use_flags)
 {
-	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)
-{
+	*out_format = format;
+	*out_use_flags = 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;
+		if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE)) {
+			*out_format = DRM_FORMAT_NV12;
+		} else {
+			/* HACK: See b/28671744 */
+			*out_format = DRM_FORMAT_XBGR8888;
+			*out_use_flags &= ~BO_USE_HW_VIDEO_ENCODER;
+		}
+		break;
 	case DRM_FORMAT_FLEX_YCbCr_420_888:
 		/* Common flexible video format. */
-		return DRM_FORMAT_NV12;
+		*out_format = DRM_FORMAT_NV12;
+		break;
+	case DRM_FORMAT_YVU420_ANDROID:
+		*out_use_flags &= ~BO_USE_SCANOUT;
+		break;
 	default:
-		return format;
+		break;
 	}
 }
diff --git a/helpers.h b/drv_helpers.h
similarity index 77%
rename from helpers.h
rename to drv_helpers.h
index d906dcf..edb69bf 100644
--- a/helpers.h
+++ b/drv_helpers.h
@@ -4,22 +4,20 @@
  * found in the LICENSE file.
  */
 
-#ifndef HELPERS_H
-#define HELPERS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
+#ifndef DRV_HELPERS_H
+#define DRV_HELPERS_H
 
 #include <stdbool.h>
 
 #include "drv.h"
-#include "helpers_array.h"
+#include "drv_array_helpers.h"
 
 #ifndef PAGE_SIZE
 #define PAGE_SIZE 0x1000
 #endif
 
+struct format_metadata;
+
 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);
@@ -35,11 +33,7 @@
 int drv_prime_bo_import(struct bo *bo, struct drv_import_fd_data *data);
 void *drv_dumb_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags);
 int drv_bo_munmap(struct bo *bo, struct vma *vma);
-int drv_mapping_destroy(struct bo *bo);
 int drv_get_prot(uint32_t map_flags);
-uintptr_t drv_get_reference_count(struct driver *drv, struct bo *bo, size_t plane);
-void drv_increment_reference_count(struct driver *drv, struct bo *bo, size_t plane);
-void drv_decrement_reference_count(struct driver *drv, struct bo *bo, size_t plane);
 void drv_add_combination(struct driver *drv, uint32_t format, struct format_metadata *metadata,
 			 uint64_t usage);
 void drv_add_combinations(struct driver *drv, const uint32_t *formats, uint32_t num_formats,
@@ -50,11 +44,8 @@
 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
+void drv_resolve_format_and_use_flags_helper(struct driver *drv, uint32_t format,
+					     uint64_t use_flags, uint32_t *out_format,
+					     uint64_t *out_use_flags);
 
 #endif
diff --git a/drv_priv.h b/drv_priv.h
index c720077..d2da440 100644
--- a/drv_priv.h
+++ b/drv_priv.h
@@ -34,7 +34,7 @@
 	 * specific metadata.  It's easiest just to stuff all the metadata here rather than
 	 * having two metadata structs.
 	 */
-	uint64_t blob_id;
+	uint32_t blob_id;
 	uint32_t map_info;
 	int32_t memory_idx;
 	int32_t physical_device_idx;
@@ -64,10 +64,11 @@
 	int fd;
 	const struct backend *backend;
 	void *priv;
+	pthread_mutex_t buffer_table_lock;
 	void *buffer_table;
+	pthread_mutex_t mappings_lock;
 	struct drv_array *mappings;
 	struct drv_array *combos;
-	pthread_mutex_t driver_lock;
 	bool compression;
 };
 
@@ -84,16 +85,22 @@
 	int (*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);
 	int (*bo_create_from_metadata)(struct bo *bo);
+	/* Called for every non-test-buffer BO on free */
+	int (*bo_release)(struct bo *bo);
+	/* Called on free if this bo is the last object referencing the contained GEM BOs */
 	int (*bo_destroy)(struct bo *bo);
 	int (*bo_import)(struct bo *bo, struct drv_import_fd_data *data);
 	void *(*bo_map)(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags);
 	int (*bo_unmap)(struct bo *bo, struct vma *vma);
 	int (*bo_invalidate)(struct bo *bo, struct mapping *mapping);
 	int (*bo_flush)(struct bo *bo, struct mapping *mapping);
-	uint32_t (*resolve_format)(struct driver *drv, uint32_t format, uint64_t use_flags);
+	void (*resolve_format_and_use_flags)(struct driver *drv, uint32_t format,
+					     uint64_t use_flags, uint32_t *out_format,
+					     uint64_t *out_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 (*get_max_texture_2d_size)(struct driver *drv);
 };
 
 // clang-format off
diff --git a/dumb_driver.c b/dumb_driver.c
index f5a62aa..ef7dd36 100644
--- a/dumb_driver.c
+++ b/dumb_driver.c
@@ -4,8 +4,10 @@
  * found in the LICENSE file.
  */
 
+#include <errno.h>
+
+#include "drv_helpers.h"
 #include "drv_priv.h"
-#include "helpers.h"
 #include "util.h"
 
 #define INIT_DUMB_DRIVER(driver)                                                                   \
@@ -13,15 +15,17 @@
 		.name = #driver,                                                                   \
 		.init = dumb_driver_init,                                                          \
 		.bo_create = drv_dumb_bo_create,                                                   \
+		.bo_create_with_modifiers = dumb_bo_create_with_modifiers,                         \
 		.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_and_use_flags = drv_resolve_format_and_use_flags_helper,           \
 	};
 
 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 };
+						   DRM_FORMAT_BGR888,	DRM_FORMAT_RGB565 };
 
 static const uint32_t texture_only_formats[] = { DRM_FORMAT_NV12, DRM_FORMAT_NV21,
 						 DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID };
@@ -42,6 +46,18 @@
 	return drv_modify_linear_combinations(drv);
 }
 
+static int dumb_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint32_t height,
+					 uint32_t format, const uint64_t *modifiers, uint32_t count)
+{
+	for (uint32_t i = 0; i < count; i++) {
+		if (modifiers[i] == DRM_FORMAT_MOD_LINEAR) {
+			return drv_dumb_bo_create(bo, width, height, format, 0);
+		}
+	}
+
+	return -EINVAL;
+}
+
 INIT_DUMB_DRIVER(evdi)
 INIT_DUMB_DRIVER(komeda)
 INIT_DUMB_DRIVER(marvell)
diff --git a/external/i915_drm.h b/external/i915_drm.h
index f5991a8..e301c5f 100644
--- a/external/i915_drm.h
+++ b/external/i915_drm.h
@@ -359,7 +359,7 @@
 #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
+#define DRM_I915_GEM_CREATE_EXT		0x3c
 /* Must be kept compact -- no holes */
 
 #define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
@@ -392,7 +392,7 @@
 #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_CREATE_EXT	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CREATE_EXT, 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)
@@ -424,7 +424,6 @@
 #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.
@@ -725,27 +724,6 @@
 	__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;
@@ -1645,53 +1623,30 @@
 #define I915_CONTEXT_PARAM_PERSISTENCE	0xb
 
 /*
- * I915_CONTEXT_PARAM_PROTECTED_CONTENT:
+ * I915_CONTEXT_PARAM_RINGSIZE:
  *
- * 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.
+ * Sets the size of the CS ringbuffer to use for logical ring contexts. This
+ * applies a limit of how many batches can be queued to HW before the caller
+ * is blocked due to lack of space for more commands.
+ *
+ * Only reliably possible to be set prior to first use, i.e. during
+ * construction. At any later point, the current execution must be flushed as
+ * the ring can only be changed while the context is idle. Note, the ringsize
+ * can be specified as a constructor property, see
+ * I915_CONTEXT_CREATE_EXT_SETPARAM, but can also be set later if required.
+ *
+ * Only applies to the current set of engine and lost when those engines
+ * are replaced by a new mapping (see I915_CONTEXT_PARAM_ENGINES).
+ *
+ * Must be between 4 - 512 KiB, in intervals of page size [4 KiB].
+ * Default is 16 KiB.
  */
-#define I915_CONTEXT_PARAM_PROTECTED_CONTENT    0xd
+#define I915_CONTEXT_PARAM_RINGSIZE	0xc
 /* 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
  *
@@ -1892,76 +1847,6 @@
 	__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.
@@ -2086,6 +1971,17 @@
 	 */
 	DRM_I915_PERF_PROP_HOLD_PREEMPTION,
 
+	/**
+	 * Specifying this pins all contexts to the specified SSEU power
+	 * configuration for the duration of the recording.
+	 *
+	 * This parameter's value is a pointer to a struct
+	 * drm_i915_gem_context_param_sseu.
+	 *
+	 * This property is available in perf revision 4.
+	 */
+	DRM_I915_PERF_PROP_GLOBAL_SSEU,
+
 	DRM_I915_PERF_PROP_MAX /* non-ABI */
 };
 
@@ -2415,6 +2311,77 @@
 	__u8 data[];
 };
 
+/**
+ * struct drm_i915_gem_create_ext - Existing gem_create behaviour, with added
+ * extension support using struct i915_user_extension.
+ *
+ * Note that in the future we want to have our buffer flags here, at least for
+ * the stuff that is immutable. Previously we would have two ioctls, one to
+ * create the object with gem_create, and another to apply various parameters,
+ * however this creates some ambiguity for the params which are considered
+ * immutable. Also in general we're phasing out the various SET/GET ioctls.
+ */
+struct drm_i915_gem_create_ext {
+	/**
+	 * @size: Requested size for the object.
+	 *
+	 * The (page-aligned) allocated size for the object will be returned.
+	 *
+	 */
+	__u64 size;
+	/**
+	 * @handle: Returned handle for the object.
+	 *
+	 * Object handles are nonzero.
+	 */
+	__u32 handle;
+	/** @flags: MBZ */
+	__u32 flags;
+	/**
+	 * @extensions: The chain of extensions to apply to this object.
+	 *
+	 * This will be useful in the future when we need to support several
+	 * different extensions, and we need to apply more than one when
+	 * creating the object. See struct i915_user_extension.
+	 *
+	 * If we don't supply any extensions then we get the same old gem_create
+	 * behaviour.
+	 *
+	 * For I915_GEM_CREATE_EXT_PROTECTED_CONTENT usage see
+	 * struct drm_i915_gem_create_ext_protected_content.
+	 */
+#define I915_GEM_CREATE_EXT_PROTECTED_CONTENT 1
+	__u64 extensions;
+};
+
+/**
+ * struct drm_i915_gem_create_ext_protected_content - The
+ * I915_OBJECT_PARAM_PROTECTED_CONTENT extension.
+ *
+ * If this extension is provided, buffer contents are expected to be protected
+ * by PXP encryption and require decryption for scan out and processing. This
+ * is only possible on platforms that have PXP enabled, on all other scenarios
+ * using this extension will cause the ioctl to fail and return -ENODEV. The
+ * flags parameter is reserved for future expansion and must currently be set
+ * to zero.
+ *
+ * The buffer contents are considered invalid after a PXP session teardown.
+ *
+ * The encryption is guaranteed to be processed correctly only if the object
+ * is submitted with a context created using the
+ * I915_CONTEXT_PARAM_PROTECTED_CONTENT flag. This will also enable extra checks
+ * at submission time on the validity of the objects involved.
+ */
+struct drm_i915_gem_create_ext_protected_content {
+	/** @base: Extension link. See struct i915_user_extension. */
+	struct i915_user_extension base;
+	/** @flags: reserved for future usage, currently MBZ */
+	__u32 flags;
+};
+
+/* ID of the protected content session managed by i915 when PXP is active */
+#define I915_PROTECTED_CONTENT_DEFAULT_SESSION 0xf
+
 #if defined(__cplusplus)
 }
 #endif
diff --git a/external/virtgpu_cross_domain_protocol.h b/external/virtgpu_cross_domain_protocol.h
index eaeebd3..afae541 100644
--- a/external/virtgpu_cross_domain_protocol.h
+++ b/external/virtgpu_cross_domain_protocol.h
@@ -10,11 +10,43 @@
 // Cross-domain commands (only a maximum of 255 supported)
 #define CROSS_DOMAIN_CMD_INIT 1
 #define CROSS_DOMAIN_CMD_GET_IMAGE_REQUIREMENTS 2
+#define CROSS_DOMAIN_CMD_POLL 3
+#define CROSS_DOMAIN_CMD_SEND 4
+#define CROSS_DOMAIN_CMD_RECEIVE 5
+#define CROSS_DOMAIN_CMD_READ 6
+#define CROSS_DOMAIN_CMD_WRITE 7
 
 // Channel types (must match rutabaga channel types)
 #define CROSS_DOMAIN_CHANNEL_TYPE_WAYLAND 0x0001
 #define CROSS_DOMAIN_CHANNEL_TYPE_CAMERA 0x0002
 
+// The maximum number of identifiers (value based on wp_linux_dmabuf)
+#define CROSS_DOMAIN_MAX_IDENTIFIERS 4
+
+// virtgpu memory resource ID.  Also works with non-blob memory resources,
+// despite the name.
+#define CROSS_DOMAIN_ID_TYPE_VIRTGPU_BLOB 1
+
+// virtgpu synchronization resource id.
+#define CROSS_DOMAIN_ID_TYPE_VIRTGPU_SYNC 2
+
+// ID for Wayland pipe used for reading.  The reading is done by the guest proxy
+// and the host proxy.  The host sends the write end of the proxied pipe over
+// the host Wayland socket.
+#define CROSS_DOMAIN_ID_TYPE_READ_PIPE 3
+
+// ID for Wayland pipe used for writing.  The writing is done by the guest and
+// the host proxy. The host receives the write end of the pipe over the host
+// Wayland socket.
+#define CROSS_DOMAIN_ID_TYPE_WRITE_PIPE 4
+
+// No ring used
+#define CROSS_DOMAIN_RING_NONE 0xffffffff
+// A ring for metadata queries.
+#define CROSS_DOMAIN_QUERY_RING 0
+// A ring based on this particular context's channel.
+#define CROSS_DOMAIN_CHANNEL_RING 1
+
 struct CrossDomainCapabilities {
 	uint32_t version;
 	uint32_t supported_channels;
@@ -27,9 +59,8 @@
 	uint32_t offsets[4];
 	uint64_t modifier;
 	uint64_t size;
-	uint64_t blob_id;
+	uint32_t blob_id;
 	uint32_t map_info;
-	uint32_t pad;
 	int32_t memory_idx;
 	int32_t physical_device_idx;
 };
@@ -55,4 +86,26 @@
 	uint32_t flags;
 };
 
+struct CrossDomainPoll {
+	struct CrossDomainHeader hdr;
+	uint64_t pad;
+};
+
+struct CrossDomainSendReceive {
+	struct CrossDomainHeader hdr;
+	uint32_t num_identifiers;
+	uint32_t opaque_data_size;
+	uint32_t identifiers[CROSS_DOMAIN_MAX_IDENTIFIERS];
+	uint32_t identifier_types[CROSS_DOMAIN_MAX_IDENTIFIERS];
+	uint32_t identifier_sizes[CROSS_DOMAIN_MAX_IDENTIFIERS];
+};
+
+struct CrossDomainReadWrite {
+	struct CrossDomainHeader hdr;
+	uint32_t identifier;
+	uint32_t hang_up;
+	uint32_t opaque_data_size;
+	uint32_t pad;
+};
+
 #endif
diff --git a/external/virtgpu_drm.h b/external/virtgpu_drm.h
index 9b46138..7720900 100644
--- a/external/virtgpu_drm.h
+++ b/external/virtgpu_drm.h
@@ -51,11 +51,11 @@
 
 #define VIRTGPU_EXECBUF_FENCE_FD_IN	0x01
 #define VIRTGPU_EXECBUF_FENCE_FD_OUT	0x02
-#define VIRTGPU_EXECBUF_FENCE_CONTEXT	0x04
+#define VIRTGPU_EXECBUF_RING_IDX	0x04
 #define VIRTGPU_EXECBUF_FLAGS  (\
 		VIRTGPU_EXECBUF_FENCE_FD_IN |\
 		VIRTGPU_EXECBUF_FENCE_FD_OUT |\
-		VIRTGPU_EXECBUF_FENCE_CONTEXT |\
+		VIRTGPU_EXECBUF_RING_IDX |\
 		0)
 
 struct drm_virtgpu_map {
@@ -208,8 +208,9 @@
 	__u64 blob_id;
 };
 
-#define VIRTGPU_CONTEXT_PARAM_CAPSET_ID           0x0001
-#define VIRTGPU_CONTEXT_PARAM_NUM_FENCE_CONTEXTS  0x0002
+#define VIRTGPU_CONTEXT_PARAM_CAPSET_ID       0x0001
+#define VIRTGPU_CONTEXT_PARAM_NUM_RINGS       0x0002
+#define VIRTGPU_CONTEXT_PARAM_POLL_RINGS_MASK 0x0003
 struct drm_virtgpu_context_set_param {
 	__u64 param;
 	__u64 value;
diff --git a/exynos.c b/exynos.c
deleted file mode 100644
index 5862643..0000000
--- a/exynos.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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_EXYNOS
-
-// clang-format off
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <xf86drm.h>
-#include <exynos_drm.h>
-// clang-format on
-
-#include "drv_priv.h"
-#include "helpers.h"
-#include "util.h"
-
-static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 };
-
-static const uint32_t texture_source_formats[] = { DRM_FORMAT_NV12 };
-
-static int exynos_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 exynos_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
-			    uint64_t use_flags)
-{
-	size_t plane;
-
-	if (format == DRM_FORMAT_NV12) {
-		uint32_t chroma_height;
-		/* V4L2 s5p-mfc requires width to be 16 byte aligned and height 32. */
-		width = ALIGN(width, 16);
-		height = ALIGN(height, 32);
-		chroma_height = ALIGN(height / 2, 32);
-		bo->meta.strides[0] = bo->meta.strides[1] = width;
-		/* MFC v8+ requires 64 byte padding in the end of luma and chroma buffers. */
-		bo->meta.sizes[0] = bo->meta.strides[0] * height + 64;
-		bo->meta.sizes[1] = bo->meta.strides[1] * chroma_height + 64;
-		bo->meta.offsets[0] = bo->meta.offsets[1] = 0;
-		bo->meta.total_size = bo->meta.sizes[0] + bo->meta.sizes[1];
-	} else if (format == DRM_FORMAT_XRGB8888 || format == DRM_FORMAT_ARGB8888) {
-		bo->meta.strides[0] = drv_stride_from_format(format, width, 0);
-		bo->meta.total_size = bo->meta.sizes[0] = height * bo->meta.strides[0];
-		bo->meta.offsets[0] = 0;
-	} else {
-		drv_log("unsupported format %X\n", format);
-		assert(0);
-		return -EINVAL;
-	}
-
-	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 };
-
-		gem_create.size = size;
-		gem_create.flags = EXYNOS_BO_NONCONTIG;
-
-		ret = drmIoctl(bo->drv->fd, DRM_IOCTL_EXYNOS_GEM_CREATE, &gem_create);
-		if (ret) {
-			drv_log("DRM_IOCTL_EXYNOS_GEM_CREATE failed (size=%zu)\n", size);
-			ret = -errno;
-			goto cleanup_planes;
-		}
-
-		bo->handles[plane].u32 = gem_create.handle;
-	}
-
-	return 0;
-
-cleanup_planes:
-	for (; plane != 0; plane--) {
-		struct drm_gem_close gem_close = { 0 };
-
-		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) {
-			drv_log("DRM_IOCTL_GEM_CLOSE failed: %d\n", gem_close_ret);
-		}
-	}
-
-	return ret;
-}
-
-/*
- * Use dumb mapping with exynos even though a GEM buffer is created.
- * libdrm does the same thing in exynos_drm.c
- */
-const struct backend backend_exynos = {
-	.name = "exynos",
-	.init = exynos_init,
-	.bo_create = exynos_bo_create,
-	.bo_destroy = drv_gem_bo_destroy,
-	.bo_import = drv_prime_bo_import,
-	.bo_map = drv_dumb_bo_map,
-	.bo_unmap = drv_bo_munmap,
-};
-
-#endif
diff --git a/gbm.c b/gbm.c
index ecbfb88..190347e 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: See b/132939420. 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 virgl_resolve_use_flags.
 	 */
 	if (format == GBM_FORMAT_YVU420 && (usage & GBM_BO_USE_LINEAR))
 		format = DRM_FORMAT_YVU420_ANDROID;
diff --git a/i915.c b/i915.c
index 9de38b2..055c582 100644
--- a/i915.c
+++ b/i915.c
@@ -15,9 +15,9 @@
 #include <unistd.h>
 #include <xf86drm.h>
 
+#include "drv_helpers.h"
 #include "drv_priv.h"
 #include "external/i915_drm.h"
-#include "helpers.h"
 #include "util.h"
 
 #define I915_CACHELINE_SIZE 64
@@ -37,7 +37,8 @@
 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,
+static const uint64_t gen12_modifier_order[] = { I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
+						 I915_FORMAT_MOD_Y_TILED, I915_FORMAT_MOD_X_TILED,
 						 DRM_FORMAT_MOD_LINEAR };
 
 struct modifier_support_t {
@@ -58,13 +59,50 @@
 {
 	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 };
+	const uint16_t gen4_ids[] = { 0x29A2, 0x2992, 0x2982, 0x2972, 0x2A02, 0x2A12, 0x2A42,
+				      0x2E02, 0x2E12, 0x2E22, 0x2E32, 0x2E42, 0x2E92 };
+	const uint16_t gen5_ids[] = { 0x0042, 0x0046 };
+	const uint16_t gen6_ids[] = { 0x0102, 0x0112, 0x0122, 0x0106, 0x0116, 0x0126, 0x010A };
+	const uint16_t gen7_ids[] = {
+		0x0152, 0x0162, 0x0156, 0x0166, 0x015a, 0x016a, 0x0402, 0x0412, 0x0422,
+		0x0406, 0x0416, 0x0426, 0x040A, 0x041A, 0x042A, 0x040B, 0x041B, 0x042B,
+		0x040E, 0x041E, 0x042E, 0x0C02, 0x0C12, 0x0C22, 0x0C06, 0x0C16, 0x0C26,
+		0x0C0A, 0x0C1A, 0x0C2A, 0x0C0B, 0x0C1B, 0x0C2B, 0x0C0E, 0x0C1E, 0x0C2E,
+		0x0A02, 0x0A12, 0x0A22, 0x0A06, 0x0A16, 0x0A26, 0x0A0A, 0x0A1A, 0x0A2A,
+		0x0A0B, 0x0A1B, 0x0A2B, 0x0A0E, 0x0A1E, 0x0A2E, 0x0D02, 0x0D12, 0x0D22,
+		0x0D06, 0x0D16, 0x0D26, 0x0D0A, 0x0D1A, 0x0D2A, 0x0D0B, 0x0D1B, 0x0D2B,
+		0x0D0E, 0x0D1E, 0x0D2E, 0x0F31, 0x0F32, 0x0F33, 0x0157, 0x0155
+	};
+	const uint16_t gen8_ids[] = { 0x22B0, 0x22B1, 0x22B2, 0x22B3, 0x1602, 0x1606,
+				      0x160A, 0x160B, 0x160D, 0x160E, 0x1612, 0x1616,
+				      0x161A, 0x161B, 0x161D, 0x161E, 0x1622, 0x1626,
+				      0x162A, 0x162B, 0x162D, 0x162E };
+	const uint16_t gen9_ids[] = {
+		0x1902, 0x1906, 0x190A, 0x190B, 0x190E, 0x1912, 0x1913, 0x1915, 0x1916, 0x1917,
+		0x191A, 0x191B, 0x191D, 0x191E, 0x1921, 0x1923, 0x1926, 0x1927, 0x192A, 0x192B,
+		0x192D, 0x1932, 0x193A, 0x193B, 0x193D, 0x0A84, 0x1A84, 0x1A85, 0x5A84, 0x5A85,
+		0x3184, 0x3185, 0x5902, 0x5906, 0x590A, 0x5908, 0x590B, 0x590E, 0x5913, 0x5915,
+		0x5917, 0x5912, 0x5916, 0x591A, 0x591B, 0x591D, 0x591E, 0x5921, 0x5923, 0x5926,
+		0x5927, 0x593B, 0x591C, 0x87C0, 0x87CA, 0x3E90, 0x3E93, 0x3E99, 0x3E9C, 0x3E91,
+		0x3E92, 0x3E96, 0x3E98, 0x3E9A, 0x3E9B, 0x3E94, 0x3EA9, 0x3EA5, 0x3EA6, 0x3EA7,
+		0x3EA8, 0x3EA1, 0x3EA4, 0x3EA0, 0x3EA3, 0x3EA2, 0x9B21, 0x9BA0, 0x9BA2, 0x9BA4,
+		0x9BA5, 0x9BA8, 0x9BAA, 0x9BAB, 0x9BAC, 0x9B41, 0x9BC0, 0x9BC2, 0x9BC4, 0x9BC5,
+		0x9BC6, 0x9BC8, 0x9BCA, 0x9BCB, 0x9BCC, 0x9BE6, 0x9BF6
+	};
+	const uint16_t gen11_ids[] = { 0x8A50, 0x8A51, 0x8A52, 0x8A53, 0x8A54, 0x8A56, 0x8A57,
+				       0x8A58, 0x8A59, 0x8A5A, 0x8A5B, 0x8A5C, 0x8A5D, 0x8A71,
+				       0x4500, 0x4541, 0x4551, 0x4555, 0x4557, 0x4571, 0x4E51,
+				       0x4E55, 0x4E57, 0x4E61, 0x4E71 };
+	const uint16_t gen12_ids[] = {
+		0x4c8a, 0x4c8b, 0x4c8c, 0x4c90, 0x4c9a, 0x4680, 0x4681, 0x4682, 0x4683, 0x4688,
+		0x4689, 0x4690, 0x4691, 0x4692, 0x4693, 0x4698, 0x4699, 0x4626, 0x4628, 0x462a,
+		0x46a0, 0x46a1, 0x46a2, 0x46a3, 0x46a6, 0x46a8, 0x46aa, 0x46b0, 0x46b1, 0x46b2,
+		0x46b3, 0x46c0, 0x46c1, 0x46c2, 0x46c3, 0x9A40, 0x9A49, 0x9A59, 0x9A60, 0x9A68,
+		0x9A70, 0x9A78, 0x9AC0, 0x9AC9, 0x9AD9, 0x9AF8, 0x4905, 0x4906, 0x4907, 0x4908
+	};
+	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;
@@ -73,6 +111,36 @@
 		if (gen3_ids[i] == i915->device_id)
 			i915->gen = 3;
 
+	/* Gen 4 */
+	for (i = 0; i < ARRAY_SIZE(gen4_ids); i++)
+		if (gen4_ids[i] == i915->device_id)
+			i915->gen = 4;
+
+	/* Gen 5 */
+	for (i = 0; i < ARRAY_SIZE(gen5_ids); i++)
+		if (gen5_ids[i] == i915->device_id)
+			i915->gen = 5;
+
+	/* Gen 6 */
+	for (i = 0; i < ARRAY_SIZE(gen6_ids); i++)
+		if (gen6_ids[i] == i915->device_id)
+			i915->gen = 6;
+
+	/* Gen 7 */
+	for (i = 0; i < ARRAY_SIZE(gen7_ids); i++)
+		if (gen7_ids[i] == i915->device_id)
+			i915->gen = 7;
+
+	/* Gen 8 */
+	for (i = 0; i < ARRAY_SIZE(gen8_ids); i++)
+		if (gen8_ids[i] == i915->device_id)
+			i915->gen = 8;
+
+	/* Gen 9 */
+	for (i = 0; i < ARRAY_SIZE(gen9_ids); i++)
+		if (gen9_ids[i] == i915->device_id)
+			i915->gen = 9;
+
 	/* Gen 11 */
 	for (i = 0; i < ARRAY_SIZE(gen11_ids); i++)
 		if (gen11_ids[i] == i915->device_id)
@@ -92,9 +160,9 @@
 
 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);
+	if (i915->gen == 12) {
+		i915->modifier.order = gen12_modifier_order;
+		i915->modifier.count = ARRAY_SIZE(gen12_modifier_order);
 	} else {
 		i915->modifier.order = gen_modifier_order;
 		i915->modifier.count = ARRAY_SIZE(gen_modifier_order);
@@ -249,10 +317,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;
 
@@ -316,7 +380,8 @@
  * 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)
+static bool i915_format_needs_LCU_alignment(uint32_t format, size_t plane,
+					    const struct i915_device *i915)
 {
 	switch (format) {
 	case DRM_FORMAT_NV12:
@@ -418,6 +483,11 @@
 			modifier = I915_FORMAT_MOD_Y_TILED;
 	}
 
+	/* Prevent gen 8 and earlier from trying to use a tiling modifier */
+	if (i915->gen <= 8 && format == DRM_FORMAT_ARGB8888) {
+		modifier = DRM_FORMAT_MOD_LINEAR;
+	}
+
 	switch (modifier) {
 	case DRM_FORMAT_MOD_LINEAR:
 		bo->meta.tiling = I915_TILING_NONE;
@@ -427,6 +497,10 @@
 		break;
 	case I915_FORMAT_MOD_Y_TILED:
 	case I915_FORMAT_MOD_Y_TILED_CCS:
+	/* For now support only I915_TILING_Y as this works with all
+	 * IPs(render/media/display)
+	 */
+	case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
 		bo->meta.tiling = I915_TILING_Y;
 		break;
 	}
@@ -485,6 +559,41 @@
 
 		bo->meta.num_planes = 2;
 		bo->meta.total_size = offset;
+	} else if (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS) {
+
+		/*
+		 * considering only 128 byte compression and one cache line of
+		 * aux buffer(64B) contains compression status of 4-Y tiles.
+		 * Which is 4 * (128B * 32L).
+		 * line stride(bytes) is 4 * 128B
+		 * and tile stride(lines) is 32L
+		 */
+		uint32_t stride = ALIGN(drv_stride_from_format(format, width, 0), 512);
+
+		height = ALIGN(drv_height_from_format(format, height, 0), 32);
+
+		if (i915->is_adlp && (stride > 1)) {
+			stride = 1 << (32 - __builtin_clz(stride - 1));
+			height = ALIGN(drv_height_from_format(format, height, 0), 128);
+		}
+
+		bo->meta.strides[0] = stride;
+		/* size calculation and alignment are 64KB aligned
+		 * size as per spec
+		 */
+		bo->meta.sizes[0] = ALIGN(stride * height, 65536);
+		bo->meta.offsets[0] = 0;
+
+		/* Aux buffer is linear and page aligned. It is placed after
+		 * other planes and aligned to main buffer stride.
+		 */
+		bo->meta.strides[1] = bo->meta.strides[0] / 8;
+		/* Aligned to page size */
+		bo->meta.sizes[1] = ALIGN(bo->meta.sizes[0] / 256, getpagesize());
+		bo->meta.offsets[1] = bo->meta.sizes[0];
+		/* Total number of planes & sizes */
+		bo->meta.num_planes = 2;
+		bo->meta.total_size = bo->meta.sizes[0] + bo->meta.sizes[1];
 	} else {
 		i915_bo_from_format(bo, width, height, format);
 	}
@@ -500,25 +609,20 @@
 	struct i915_device *i915 = bo->drv->priv;
 
 	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,
-		};
-
-		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_protected_content protected_content = {
+			.base = { .name = I915_GEM_CREATE_EXT_PROTECTED_CONTENT },
+			.flags = 0,
 		};
 
 		struct drm_i915_gem_create_ext create_ext = {
 			.size = bo->meta.total_size,
-			.extensions = (uintptr_t)&setparam_protected,
+			.extensions = (uintptr_t)&protected_content,
 		};
 
 		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);
+			drv_log("DRM_IOCTL_I915_GEM_CREATE_EXT failed (size=%llu) (ret=%d) \n",
+				create_ext.size, ret);
 			return -errno;
 		}
 
@@ -592,6 +696,9 @@
 	if (bo->meta.format_modifier == I915_FORMAT_MOD_Y_TILED_CCS)
 		return MAP_FAILED;
 
+	if (bo->meta.format_modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS)
+		return MAP_FAILED;
+
 	if (bo->meta.tiling == I915_TILING_NONE) {
 		struct drm_i915_gem_mmap gem_map = { 0 };
 		/* TODO(b/118799155): We don't seem to have a good way to
@@ -692,7 +799,7 @@
 	.bo_unmap = drv_bo_munmap,
 	.bo_invalidate = i915_bo_invalidate,
 	.bo_flush = i915_bo_flush,
-	.resolve_format = drv_resolve_format_helper,
+	.resolve_format_and_use_flags = drv_resolve_format_and_use_flags_helper,
 };
 
 #endif
diff --git a/mediatek.c b/mediatek.c
index de492e2..f6a4c17 100644
--- a/mediatek.c
+++ b/mediatek.c
@@ -19,8 +19,8 @@
 #include <mediatek_drm.h>
 // clang-format on
 
+#include "drv_helpers.h"
 #include "drv_priv.h"
-#include "helpers.h"
 #include "util.h"
 
 #define TILE_TYPE_LINEAR 0
@@ -36,9 +36,11 @@
 						  DRM_FORMAT_XRGB8888 };
 
 #ifdef MTK_MT8183
-static const uint32_t texture_source_formats[] = { DRM_FORMAT_NV21, DRM_FORMAT_NV12,
-						   DRM_FORMAT_YUYV, DRM_FORMAT_YVU420,
-						   DRM_FORMAT_YVU420_ANDROID };
+static const uint32_t texture_source_formats[] = {
+	DRM_FORMAT_NV21,	 DRM_FORMAT_NV12,	    DRM_FORMAT_YUYV,
+	DRM_FORMAT_YVU420,	 DRM_FORMAT_YVU420_ANDROID, DRM_FORMAT_ABGR2101010,
+	DRM_FORMAT_ABGR16161616F
+};
 #else
 static const uint32_t texture_source_formats[] = { DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID,
 						   DRM_FORMAT_NV12 };
@@ -172,6 +174,7 @@
 	int ret, prime_fd;
 	struct drm_mtk_gem_map_off gem_map = { 0 };
 	struct mediatek_private_map_data *priv;
+	void *addr = NULL;
 
 	gem_map.handle = bo->handles[0].u32;
 
@@ -187,22 +190,38 @@
 		return MAP_FAILED;
 	}
 
-	void *addr = mmap(0, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd,
-			  gem_map.offset);
+	addr = mmap(0, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd,
+		    gem_map.offset);
+	if (addr == MAP_FAILED)
+		goto out_close_prime_fd;
 
 	vma->length = bo->meta.total_size;
 
 	priv = calloc(1, sizeof(*priv));
-	priv->prime_fd = prime_fd;
-	vma->priv = priv;
+	if (!priv)
+		goto out_unmap_addr;
 
 	if (bo->meta.use_flags & BO_USE_RENDERSCRIPT) {
 		priv->cached_addr = calloc(1, bo->meta.total_size);
+		if (!priv->cached_addr)
+			goto out_free_priv;
+
 		priv->gem_addr = addr;
 		addr = priv->cached_addr;
 	}
 
+	priv->prime_fd = prime_fd;
+	vma->priv = priv;
+
 	return addr;
+
+out_free_priv:
+	free(priv);
+out_unmap_addr:
+	munmap(addr, bo->meta.total_size);
+out_close_prime_fd:
+	close(prime_fd);
+	return MAP_FAILED;
 }
 
 static int mediatek_bo_unmap(struct bo *bo, struct vma *vma)
@@ -258,36 +277,55 @@
 	return 0;
 }
 
-static uint32_t mediatek_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags)
+static void mediatek_resolve_format_and_use_flags(struct driver *drv, uint32_t format,
+						  uint64_t use_flags, uint32_t *out_format,
+						  uint64_t *out_use_flags)
 {
+	*out_format = format;
+	*out_use_flags = use_flags;
 	switch (format) {
 	case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
 #ifdef MTK_MT8183
 		/* Only MT8183 Camera subsystem offers private reprocessing
 		 * capability. CAMERA_READ indicates the buffer is intended for
 		 * reprocessing and hence given the private format for MTK. */
-		if (use_flags & BO_USE_CAMERA_READ)
-			return DRM_FORMAT_MTISP_SXYZW10;
+		if (use_flags & BO_USE_CAMERA_READ) {
+			*out_format = DRM_FORMAT_MTISP_SXYZW10;
+			break;
+		}
 #endif
-		if (use_flags & BO_USE_CAMERA_WRITE)
-			return DRM_FORMAT_NV12;
+		if (use_flags & BO_USE_CAMERA_WRITE) {
+			*out_format = DRM_FORMAT_NV12;
+			break;
+		}
 
-		/*HACK: See b/28671744 */
-		return DRM_FORMAT_XBGR8888;
+		/* HACK: See b/28671744 */
+		*out_format = DRM_FORMAT_XBGR8888;
+		*out_use_flags &= ~BO_USE_HW_VIDEO_ENCODER;
+		break;
 	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)) {
-			return DRM_FORMAT_NV12;
+			*out_format = DRM_FORMAT_NV12;
+			break;
 		}
 #endif
 		if (use_flags &
 		    (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_ENCODER)) {
-			return DRM_FORMAT_NV12;
+			*out_format = DRM_FORMAT_NV12;
+			break;
 		}
-		return DRM_FORMAT_YVU420;
+
+		/* HACK: See b/139714614 */
+		*out_format = DRM_FORMAT_YVU420;
+		*out_use_flags &= ~BO_USE_SCANOUT;
+		break;
+	case DRM_FORMAT_YVU420_ANDROID:
+		*out_use_flags &= ~BO_USE_SCANOUT;
+		break;
 	default:
-		return format;
+		break;
 	}
 }
 
@@ -302,7 +340,7 @@
 	.bo_unmap = mediatek_bo_unmap,
 	.bo_invalidate = mediatek_bo_invalidate,
 	.bo_flush = mediatek_bo_flush,
-	.resolve_format = mediatek_resolve_format,
+	.resolve_format_and_use_flags = mediatek_resolve_format_and_use_flags,
 };
 
 #endif
diff --git a/minigbm_helpers.c b/minigbm_helpers.c
index 137e5a1..cea0b48 100644
--- a/minigbm_helpers.c
+++ b/minigbm_helpers.c
@@ -273,6 +273,9 @@
 			break;
 		}
 	}
+
+	closedir(dir);
+
 	if (dfd >= 0)
 		return dfd;
 
diff --git a/msm.c b/msm.c
index 16e781f..f3be2be 100644
--- a/msm.c
+++ b/msm.c
@@ -18,8 +18,8 @@
 #include <sys/mman.h>
 #include <xf86drm.h>
 
+#include "drv_helpers.h"
 #include "drv_priv.h"
-#include "helpers.h"
 #include "util.h"
 
 /* Alignment values are based on SDM845 Gfx IP */
@@ -41,7 +41,8 @@
 						  DRM_FORMAT_XRGB8888 };
 
 static const uint32_t texture_source_formats[] = { DRM_FORMAT_NV12, DRM_FORMAT_R8,
-						   DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID };
+						   DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID,
+						   DRM_FORMAT_P010 };
 
 /*
  * Each macrotile consists of m x n (mostly 4 x 4) tiles.
@@ -94,10 +95,15 @@
 	/* NV12 format requires extra padding with platform
 	 * specific alignments for venus driver
 	 */
-	if (bo->meta.format == DRM_FORMAT_NV12) {
+	if (bo->meta.format == DRM_FORMAT_NV12 || bo->meta.format == DRM_FORMAT_P010) {
 		uint32_t y_stride, uv_stride, y_scanline, uv_scanline, y_plane, uv_plane, size,
 		    extra_padding;
 
+		// P010 has the same layout as NV12.  The difference is that each
+		// pixel in P010 takes 2 bytes, while in NV12 each pixel takes 1 byte.
+		if (bo->meta.format == DRM_FORMAT_P010)
+			width *= 2;
+
 		y_stride = ALIGN(width, VENUS_STRIDE_ALIGN);
 		uv_stride = ALIGN(width, VENUS_STRIDE_ALIGN);
 		y_scanline = ALIGN(height, VENUS_SCANLINE_ALIGN * 2);
@@ -158,7 +164,9 @@
 	case DRM_FORMAT_ABGR8888:
 	case DRM_FORMAT_XRGB8888:
 	case DRM_FORMAT_ARGB8888:
+#ifndef QCOM_DISABLE_COMPRESSED_NV12
 	case DRM_FORMAT_NV12:
+#endif
 		return 1;
 	default:
 		return 0;
@@ -252,9 +260,21 @@
 			       BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER |
 				   BO_USE_HW_VIDEO_ENCODER);
 
+	/*
+	 * Android also frequently requests YV12 formats for some camera implementations
+	 * (including the external provider implmenetation).
+	 */
+	drv_modify_combination(drv, DRM_FORMAT_YVU420_ANDROID, &LINEAR_METADATA,
+			       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);
 
+#ifdef SC_7280
+	drv_modify_combination(drv, DRM_FORMAT_P010, &LINEAR_METADATA,
+			       BO_USE_SCANOUT | BO_USE_HW_VIDEO_ENCODER);
+#endif
+
 	drv_modify_linear_combinations(drv);
 
 	if (should_avoid_ubwc() || !drv->compression)
@@ -366,6 +386,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_and_use_flags = drv_resolve_format_and_use_flags_helper,
 };
 #endif /* DRV_MSM */
diff --git a/rockchip.c b/rockchip.c
index 4ef30bc..89063ee 100644
--- a/rockchip.c
+++ b/rockchip.c
@@ -14,8 +14,8 @@
 #include <sys/mman.h>
 #include <xf86drm.h>
 
+#include "drv_helpers.h"
 #include "drv_priv.h"
-#include "helpers.h"
 #include "util.h"
 
 struct rockchip_private_map_data {
@@ -184,6 +184,7 @@
 	int ret;
 	struct rockchip_private_map_data *priv;
 	struct drm_rockchip_gem_map_off gem_map = { 0 };
+	void *addr = NULL;
 
 	/* We can only map buffers created with SW access flags, which should
 	 * have no modifiers (ie, not AFBC). */
@@ -197,20 +198,34 @@
 		return MAP_FAILED;
 	}
 
-	void *addr = mmap(0, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd,
-			  gem_map.offset);
+	addr = mmap(0, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd,
+		    gem_map.offset);
+	if (addr == MAP_FAILED)
+		return MAP_FAILED;
 
 	vma->length = bo->meta.total_size;
 
 	if (bo->meta.use_flags & BO_USE_RENDERSCRIPT) {
 		priv = calloc(1, sizeof(*priv));
+		if (!priv)
+			goto out_unmap_addr;
+
 		priv->cached_addr = calloc(1, bo->meta.total_size);
+		if (!priv->cached_addr)
+			goto out_free_priv;
+
 		priv->gem_addr = addr;
 		vma->priv = priv;
 		addr = priv->cached_addr;
 	}
 
 	return addr;
+
+out_free_priv:
+	free(priv);
+out_unmap_addr:
+	munmap(addr, bo->meta.total_size);
+	return MAP_FAILED;
 }
 
 static int rockchip_bo_unmap(struct bo *bo, struct vma *vma)
@@ -256,7 +271,7 @@
 	.bo_unmap = rockchip_bo_unmap,
 	.bo_invalidate = rockchip_bo_invalidate,
 	.bo_flush = rockchip_bo_flush,
-	.resolve_format = drv_resolve_format_helper,
+	.resolve_format_and_use_flags = drv_resolve_format_and_use_flags_helper,
 };
 
 #endif
diff --git a/vc4.c b/vc4.c
index 5ea4bc3..820e4fe 100644
--- a/vc4.c
+++ b/vc4.c
@@ -13,8 +13,8 @@
 #include <vc4_drm.h>
 #include <xf86drm.h>
 
+#include "drv_helpers.h"
 #include "drv_priv.h"
-#include "helpers.h"
 #include "util.h"
 
 static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_RGB565,
@@ -131,6 +131,7 @@
 	.bo_destroy = drv_gem_bo_destroy,
 	.bo_map = vc4_bo_map,
 	.bo_unmap = drv_bo_munmap,
+	.resolve_format_and_use_flags = drv_resolve_format_and_use_flags_helper,
 };
 
 #endif
diff --git a/virtgpu.c b/virtgpu.c
index 23e90b3..db50b46 100644
--- a/virtgpu.c
+++ b/virtgpu.c
@@ -13,7 +13,6 @@
 
 #include "drv_priv.h"
 #include "external/virtgpu_drm.h"
-#include "helpers.h"
 #include "util.h"
 #include "virtgpu.h"
 
@@ -49,7 +48,7 @@
 		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));
+			drv_log("virtgpu backend not enabling %s\n", params[i].name);
 	}
 
 	for (uint32_t i = 0; i < ARRAY_SIZE(virtgpu_backends); i++) {
diff --git a/virtgpu_cross_domain.c b/virtgpu_cross_domain.c
index b02a949..85ea1a3 100644
--- a/virtgpu_cross_domain.c
+++ b/virtgpu_cross_domain.c
@@ -9,10 +9,10 @@
 #include <sys/mman.h>
 #include <xf86drm.h>
 
+#include "drv_helpers.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"
 
@@ -36,6 +36,7 @@
 	uint32_t ring_handle;
 	void *ring_addr;
 	struct drv_array *metadata_cache;
+	pthread_mutex_t metadata_cache_lock;
 };
 
 static void cross_domain_release_private(struct driver *drv)
@@ -57,7 +58,11 @@
 		}
 	}
 
-	drv_array_destroy(priv->metadata_cache);
+	if (priv->metadata_cache)
+		drv_array_destroy(priv->metadata_cache);
+
+	pthread_mutex_destroy(&priv->metadata_cache_lock);
+
 	free(priv);
 }
 
@@ -107,7 +112,7 @@
 	exec.command = (uint64_t)&cmd[0];
 	exec.size = cmd_size;
 	if (wait) {
-		exec.flags = VIRTGPU_EXECBUF_FENCE_CONTEXT;
+		exec.flags = VIRTGPU_EXECBUF_RING_IDX;
 		exec.bo_handles = (uint64_t)&priv->ring_handle;
 		exec.num_bo_handles = 1;
 	}
@@ -150,7 +155,7 @@
 	uint32_t plane, remaining_size;
 
 	memset(&cmd_get_reqs, 0, sizeof(cmd_get_reqs));
-	pthread_mutex_lock(&drv->driver_lock);
+	pthread_mutex_lock(&priv->metadata_cache_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))
@@ -185,11 +190,11 @@
 	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));
+	memcpy(&metadata->blob_id, &addr[12], sizeof(uint32_t));
 
-	metadata->map_info = addr[14];
-	metadata->memory_idx = addr[16];
-	metadata->physical_device_idx = addr[17];
+	metadata->map_info = addr[13];
+	metadata->memory_idx = addr[14];
+	metadata->physical_device_idx = addr[15];
 
 	remaining_size = metadata->total_size;
 	for (plane = 0; plane < metadata->num_planes; plane++) {
@@ -203,7 +208,7 @@
 	drv_array_append(priv->metadata_cache, metadata);
 
 out_unlock:
-	pthread_mutex_unlock(&drv->driver_lock);
+	pthread_mutex_unlock(&priv->metadata_cache_lock);
 	return ret;
 }
 
@@ -243,7 +248,21 @@
 		return -ENOTSUP;
 
 	priv = calloc(1, sizeof(*priv));
+	if (!priv)
+		return -ENOMEM;
+
+	ret = pthread_mutex_init(&priv->metadata_cache_lock, NULL);
+	if (ret) {
+		free(priv);
+		return ret;
+	}
+
 	priv->metadata_cache = drv_array_init(sizeof(struct bo_metadata));
+	if (!priv->metadata_cache) {
+		ret = -ENOMEM;
+		goto free_private;
+	}
+
 	priv->ring_addr = MAP_FAILED;
 	drv->priv = priv;
 
@@ -269,7 +288,7 @@
 	// 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].param = VIRTGPU_CONTEXT_PARAM_NUM_RINGS;
 	ctx_set_params[1].value = 1;
 
 	init.ctx_set_params = (unsigned long long)&ctx_set_params[0];
@@ -363,7 +382,7 @@
 
 	drm_rc_blob.size = bo->meta.total_size;
 	drm_rc_blob.blob_flags = blob_flags;
-	drm_rc_blob.blob_id = bo->meta.blob_id;
+	drm_rc_blob.blob_id = (uint64_t)bo->meta.blob_id;
 
 	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB, &drm_rc_blob);
 	if (ret < 0) {
@@ -403,5 +422,5 @@
 	.bo_destroy = drv_gem_bo_destroy,
 	.bo_map = cross_domain_bo_map,
 	.bo_unmap = drv_bo_munmap,
-	.resolve_format = drv_resolve_format_helper,
+	.resolve_format_and_use_flags = drv_resolve_format_and_use_flags_helper,
 };
diff --git a/virtgpu_virgl.c b/virtgpu_virgl.c
index 32ca6a1..c159c21 100644
--- a/virtgpu_virgl.c
+++ b/virtgpu_virgl.c
@@ -12,31 +12,45 @@
 #include <sys/mman.h>
 #include <xf86drm.h>
 
+#include "drv_helpers.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_MAX_TEXTURE_2D_LEVELS 15
+#define MESA_LLVMPIPE_MAX_TEXTURE_2D_SIZE (1 << (MESA_LLVMPIPE_MAX_TEXTURE_2D_LEVELS - 1))
 #define MESA_LLVMPIPE_TILE_ORDER 6
 #define MESA_LLVMPIPE_TILE_SIZE (1 << MESA_LLVMPIPE_TILE_ORDER)
 
+// This comes from a combination of SwiftShader's VkPhysicalDeviceLimits::maxFramebufferWidth and
+// VkPhysicalDeviceLimits::maxImageDimension2D (see https://crrev.com/c/1917130).
+#define ANGLE_ON_SWIFTSHADER_MAX_TEXTURE_2D_SIZE 8192
+
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+#define VIRGL_2D_MAX_TEXTURE_2D_SIZE                                                               \
+	MIN(ANGLE_ON_SWIFTSHADER_MAX_TEXTURE_2D_SIZE, MESA_LLVMPIPE_MAX_TEXTURE_2D_SIZE)
+
 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
+	DRM_FORMAT_R8,		DRM_FORMAT_R16,		 DRM_FORMAT_YVU420,
+	DRM_FORMAT_NV12,	DRM_FORMAT_NV21,	 DRM_FORMAT_YVU420_ANDROID,
+	DRM_FORMAT_ABGR2101010, DRM_FORMAT_ABGR16161616F
 };
 
-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 };
+static const uint32_t texture_source_formats[] = {
+	DRM_FORMAT_NV21,	   DRM_FORMAT_R8,	   DRM_FORMAT_R16,	    DRM_FORMAT_RG88,
+	DRM_FORMAT_YVU420_ANDROID, DRM_FORMAT_ABGR2101010, DRM_FORMAT_ABGR16161616F
+};
 
 extern struct virtgpu_param params[];
 
@@ -63,6 +77,8 @@
 		return VIRGL_FORMAT_R8G8B8A8_UNORM;
 	case DRM_FORMAT_ABGR16161616F:
 		return VIRGL_FORMAT_R16G16B16A16_FLOAT;
+	case DRM_FORMAT_ABGR2101010:
+		return VIRGL_FORMAT_R10G10B10A2_UNORM;
 	case DRM_FORMAT_RGB565:
 		return VIRGL_FORMAT_B5G6R5_UNORM;
 	case DRM_FORMAT_R8:
@@ -330,12 +346,10 @@
 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);
+	if (params[param_3d].value) {
+		if ((use_flags & BO_USE_SCANOUT) &&
+		    !virgl_supports_combination_natively(drv, drm_format, BO_USE_SCANOUT)) {
+			drv_log("Strip scanout on format: %d\n", drm_format);
 			use_flags &= ~BO_USE_SCANOUT;
 		}
 
@@ -361,8 +375,8 @@
 		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)
+static int virgl_2d_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);
@@ -391,6 +405,8 @@
 	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_GPU_DATA_BUFFER, &bind, VIRGL_BIND_LINEAR);
+	handle_flag(&use_flags, BO_USE_FRONT_RENDERING, &bind, VIRGL_BIND_LINEAR);
 
 	if (use_flags & BO_USE_PROTECTED) {
 		handle_flag(&use_flags, BO_USE_PROTECTED, &bind, VIRGL_BIND_MINIGBM_PROTECTED);
@@ -420,14 +436,6 @@
 	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);
 
@@ -512,6 +520,16 @@
 		    gem_map.offset);
 }
 
+static uint32_t virgl_3d_get_max_texture_2d_size(struct driver *drv)
+{
+	struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
+
+	if (priv->caps.v2.max_texture_2d_size)
+		return priv->caps.v2.max_texture_2d_size;
+
+	return UINT32_MAX;
+}
+
 static int virgl_get_caps(struct driver *drv, union virgl_caps *caps, int *caps_is_v2)
 {
 	int ret;
@@ -569,6 +587,9 @@
 	struct virgl_priv *priv;
 
 	priv = calloc(1, sizeof(*priv));
+	if (!priv)
+		return -ENOMEM;
+
 	drv->priv = priv;
 
 	virgl_init_params_and_caps(drv);
@@ -582,6 +603,12 @@
 		virgl_add_combinations(drv, texture_source_formats,
 				       ARRAY_SIZE(texture_source_formats), &LINEAR_METADATA,
 				       BO_USE_TEXTURE_MASK);
+		/* NV12 with scanout must flow through virgl_add_combination, so that the native
+		 * support is checked and scanout use_flag can be conditionally stripped. */
+		virgl_add_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA,
+				      BO_USE_TEXTURE_MASK | BO_USE_CAMERA_READ |
+					  BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER |
+					  BO_USE_HW_VIDEO_ENCODER | BO_USE_SCANOUT);
 	} else {
 		/* Virtio primary plane only allows this format. */
 		virgl_add_combination(drv, DRM_FORMAT_XRGB8888, &LINEAR_METADATA,
@@ -598,28 +625,19 @@
 		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);
+		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);
 	}
 
 	/* 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);
+			      BO_USE_SW_MASK | BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
 	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_HW_VIDEO_ENCODER | BO_USE_GPU_DATA_BUFFER);
 
 	if (!priv->host_gbm_enabled) {
 		drv_modify_combination(drv, DRM_FORMAT_ABGR8888, &LINEAR_METADATA,
@@ -663,8 +681,10 @@
 	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;
+
+	// For now, all blob use cases are cross device. When we add wider
+	// support for blobs, we can revisit making this unconditional.
+	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);
@@ -714,16 +734,17 @@
 	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)))
+	// Use regular resources if only the GPU needs efficient access. Blob resource is a better
+	// fit for BO_USE_GPU_DATA_BUFFER which is mapped to VIRGL_BIND_LINEAR.
+	if (!(use_flags & (BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN | BO_USE_LINEAR |
+			   BO_USE_NON_GPU_HW | BO_USE_GPU_DATA_BUFFER)))
 		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_YVU420_ANDROID:
 	case DRM_FORMAT_NV12:
 		// Knowing buffer metadata at buffer creation isn't yet supported, so buffers
 		// can't be properly mapped into the guest.
@@ -743,7 +764,7 @@
 	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);
+		return virgl_2d_dumb_bo_create(bo, width, height, format, use_flags);
 }
 
 static int virgl_bo_destroy(struct bo *bo)
@@ -934,28 +955,97 @@
 	return 0;
 }
 
-static uint32_t virgl_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags)
+static void virgl_3d_resolve_format_and_use_flags(struct driver *drv, uint32_t format,
+						  uint64_t use_flags, uint32_t *out_format,
+						  uint64_t *out_use_flags)
 {
+	*out_format = format;
+	*out_use_flags = 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;
+		if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE)) {
+			*out_format = DRM_FORMAT_NV12;
+		} else {
+			/* HACK: See b/28671744 */
+			*out_format = DRM_FORMAT_XBGR8888;
+			*out_use_flags &= ~BO_USE_HW_VIDEO_ENCODER;
+		}
+		break;
 	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;
+		/* All of our host drivers prefer NV12 as their flexible media format.
+		 * If that changes, this will need to be modified. */
+		*out_format = DRM_FORMAT_NV12;
+		/* fallthrough */
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_XRGB8888:
+		/* These are the scanout capable formats to the guest. Strip scanout use_flag if the
+		 * host does not natively support scanout on the requested format. */
+		if ((use_flags & BO_USE_SCANOUT) &&
+		    !virgl_supports_combination_natively(drv, format, BO_USE_SCANOUT))
+			*out_use_flags &= ~BO_USE_SCANOUT;
+		break;
+	case DRM_FORMAT_YVU420_ANDROID:
+		*out_use_flags &= ~BO_USE_SCANOUT;
+		/* HACK: See b/172389166. Also see gbm_bo_create. */
+		*out_use_flags |= BO_USE_LINEAR;
+		break;
 	default:
-		return format;
+		break;
 	}
 }
+
+static void virgl_2d_resolve_format_and_use_flags(uint32_t format, uint64_t use_flags,
+						  uint32_t *out_format, uint64_t *out_use_flags)
+{
+	*out_format = format;
+	*out_use_flags = use_flags;
+
+	/* HACK: See crrev/c/1849773 */
+	if (format != DRM_FORMAT_XRGB8888)
+		*out_use_flags &= ~BO_USE_SCANOUT;
+
+	switch (format) {
+	case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
+		/* Camera subsystem requires NV12. */
+		if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE)) {
+			*out_format = DRM_FORMAT_NV12;
+		} else {
+			/* HACK: See b/28671744 */
+			*out_format = DRM_FORMAT_XBGR8888;
+			*out_use_flags &= ~BO_USE_HW_VIDEO_ENCODER;
+		}
+		break;
+	case DRM_FORMAT_FLEX_YCbCr_420_888:
+		*out_format = DRM_FORMAT_YVU420_ANDROID;
+		/* fallthrough */
+	case DRM_FORMAT_YVU420_ANDROID:
+		*out_use_flags &= ~BO_USE_SCANOUT;
+		/* HACK: See b/172389166. Also see gbm_bo_create. */
+		*out_use_flags |= BO_USE_LINEAR;
+		break;
+	default:
+		break;
+	}
+}
+
+static void virgl_resolve_format_and_use_flags(struct driver *drv, uint32_t format,
+					       uint64_t use_flags, uint32_t *out_format,
+					       uint64_t *out_use_flags)
+{
+	if (params[param_3d].value) {
+		return virgl_3d_resolve_format_and_use_flags(drv, format, use_flags, out_format,
+							     out_use_flags);
+	} else {
+		return virgl_2d_resolve_format_and_use_flags(format, use_flags, out_format,
+							     out_use_flags);
+	}
+}
+
 static int virgl_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES],
 			       uint32_t offsets[DRV_MAX_PLANES], uint64_t *format_modifier)
 {
@@ -973,21 +1063,30 @@
 		return ret;
 	}
 
-	for (uint32_t plane = 0; plane < bo->meta.num_planes; plane++) {
+	for (uint32_t plane = 0; plane < DRV_MAX_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];
-		}
+		if (!res_info.strides[plane])
+			break;
+
+		strides[plane] = res_info.strides[plane];
+		offsets[plane] = res_info.offsets[plane];
 	}
 	*format_modifier = res_info.format_modifier;
 
 	return 0;
 }
 
+static uint32_t virgl_get_max_texture_2d_size(struct driver *drv)
+{
+	if (params[param_3d].value)
+		return virgl_3d_get_max_texture_2d_size(drv);
+	else
+		return VIRGL_2D_MAX_TEXTURE_2D_SIZE;
+}
+
 const struct backend virtgpu_virgl = { .name = "virtgpu_virgl",
 				       .init = virgl_init,
 				       .close = virgl_close,
@@ -998,5 +1097,7 @@
 				       .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 };
+				       .resolve_format_and_use_flags =
+					   virgl_resolve_format_and_use_flags,
+				       .resource_info = virgl_resource_info,
+				       .get_max_texture_2d_size = virgl_get_max_texture_2d_size };