minigbm: cros_gralloc: refactor for future HALs

We want the ability to support gralloc0, gralloc1 and HIDL
gralloc in this repo. This commit moves gralloc0 specific code
to the gralloc0 subdirectory, and refactors the rest of the code
so it can be eventually used by whichever APIs we choose to
implement.

In addition, all of the data by the module is now handled by
managed pointers instead of process data, since we get a number
of crash reports when we try to access data in gralloc_close().

BUG=b:62069164, b:62221166
TEST=gralloctest all, Android boots, Youtube videos, 5-10
     CTS tests

Change-Id: Ic29a777573936216d99498d0b814ea50015fd435
Reviewed-on: https://chromium-review.googlesource.com/521794
Commit-Ready: Gurchetan Singh <gurchetansingh@chromium.org>
Tested-by: Gurchetan Singh <gurchetansingh@chromium.org>
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
diff --git a/Android.gralloc.mk b/Android.gralloc.mk
index 4a0b125..ff269c0 100644
--- a/Android.gralloc.mk
+++ b/Android.gralloc.mk
@@ -5,6 +5,7 @@
 LOCAL_CPP_EXTENSION := .cc
 
 LOCAL_SRC_FILES += \
-	cros_gralloc/cros_alloc_device.cc \
+	cros_gralloc/cros_gralloc_buffer.cc \
+	cros_gralloc/cros_gralloc_driver.cc \
 	cros_gralloc/cros_gralloc_helpers.cc \
-	cros_gralloc/cros_gralloc_module.cc
+	cros_gralloc/gralloc0/gralloc0.cc
diff --git a/Android.mk b/Android.mk
index d5225ec..c4798ad 100644
--- a/Android.mk
+++ b/Android.mk
@@ -36,7 +36,7 @@
 
 include $(MINIGBM_GRALLOC_MK)
 
-LOCAL_CPPFLAGS += -std=c++11 -D_GNU_SOURCE=1 -D_FILE_OFFSET_BITS=64
+LOCAL_CPPFLAGS += -std=c++14 -D_GNU_SOURCE=1 -D_FILE_OFFSET_BITS=64
 LOCAL_CFLAGS += -Wall -Wsign-compare -Wpointer-arith \
 		-Wcast-qual -Wcast-align \
 		-D_GNU_SOURCE=1 -D_FILE_OFFSET_BITS=64
diff --git a/cros_gralloc/Makefile b/cros_gralloc/Makefile
index 9e1be9e..9c23e7b 100644
--- a/cros_gralloc/Makefile
+++ b/cros_gralloc/Makefile
@@ -6,6 +6,9 @@
 
 SRCS    = $(wildcard *.cc)
 SRCS   += $(wildcard ../*.c)
+
+SRCS   += $(wildcard gralloc0/*.cc)
+
 SOURCES = $(filter-out ../gbm%, $(SRCS))
 PKG_CONFIG ?= pkg-config
 
@@ -14,7 +17,7 @@
 LIBDRM_LIBS := $(shell $(PKG_CONFIG) --libs libdrm)
 
 CPPFLAGS += -Wall -fPIC -Werror -flto $(LIBDRM_CFLAGS)
-CXXFLAGS += -std=c++11
+CXXFLAGS += -std=c++14
 CFLAGS   += -std=c99
 LIBS     += -shared -lcutils -lhardware $(LIBDRM_LIBS)
 
diff --git a/cros_gralloc/cros_alloc_device.cc b/cros_gralloc/cros_alloc_device.cc
deleted file mode 100644
index 5eda6b8..0000000
--- a/cros_gralloc/cros_alloc_device.cc
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright 2016 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "cros_gralloc.h"
-
-static struct cros_gralloc_bo *cros_gralloc_bo_create(struct driver *drv, int width, int height,
-						      int format, int usage)
-{
-	uint64_t drv_usage;
-	uint32_t drv_format;
-	struct combination *combo;
-	struct cros_gralloc_bo *bo;
-
-	drv_format = cros_gralloc_convert_format(format);
-	drv_format = drv_resolve_format(drv, drv_format);
-	drv_usage = cros_gralloc_convert_flags(usage);
-
-	combo = drv_get_combination(drv, drv_format, drv_usage);
-
-	if (!combo && (usage & GRALLOC_USAGE_HW_COMPOSER)) {
-		drv_usage &= ~BO_USE_SCANOUT;
-		combo = drv_get_combination(drv, drv_format, drv_usage);
-	}
-
-	if (!combo) {
-		cros_gralloc_error("Unsupported combination -- HAL format: %u, HAL flags: %u, "
-				   "drv_format: %4.4s, drv_flags: %llu",
-				   format, usage, reinterpret_cast<char *>(&drv_format),
-				   static_cast<unsigned long long>(drv_usage));
-		return NULL;
-	}
-
-	bo = new cros_gralloc_bo();
-
-	bo->bo = drv_bo_create(drv, width, height, drv_format, drv_usage);
-	if (!bo->bo) {
-		delete bo;
-		cros_gralloc_error("Failed to create bo.");
-		return NULL;
-	}
-
-	/*
-	 * If there is a desire for more than one kernel buffer, this can be
-	 * removed once the ArcCodec and Wayland service have the ability to
-	 * send more than one fd. GL/Vulkan drivers may also have to modified.
-	 */
-	if (drv_num_buffers_per_bo(bo->bo) != 1) {
-		drv_bo_destroy(bo->bo);
-		delete bo;
-		cros_gralloc_error("Can only support one buffer per bo.");
-		return NULL;
-	}
-
-	bo->refcount = 1;
-
-	return bo;
-}
-
-static struct cros_gralloc_handle *cros_gralloc_handle_from_bo(struct bo *bo)
-{
-	uint64_t mod;
-	size_t num_planes;
-	struct cros_gralloc_handle *hnd;
-
-	hnd = new cros_gralloc_handle();
-
-	num_planes = drv_bo_get_num_planes(bo);
-
-	hnd->base.version = sizeof(hnd->base);
-	hnd->base.numFds = num_planes;
-	hnd->base.numInts = handle_data_size - num_planes;
-
-	for (size_t p = 0; p < num_planes; p++) {
-		hnd->fds[p] = drv_bo_get_plane_fd(bo, p);
-		hnd->strides[p] = drv_bo_get_plane_stride(bo, p);
-		hnd->offsets[p] = drv_bo_get_plane_offset(bo, p);
-		hnd->sizes[p] = drv_bo_get_plane_size(bo, p);
-
-		mod = drv_bo_get_plane_format_modifier(bo, p);
-		hnd->format_modifiers[2 * p] = static_cast<uint32_t>(mod >> 32);
-		hnd->format_modifiers[2 * p + 1] = static_cast<uint32_t>(mod);
-	}
-
-	hnd->width = drv_bo_get_width(bo);
-	hnd->height = drv_bo_get_height(bo);
-	hnd->format = drv_bo_get_format(bo);
-	hnd->pixel_stride = drv_bo_get_stride_in_pixels(bo);
-
-	hnd->magic = cros_gralloc_magic;
-
-	return hnd;
-}
-
-static int cros_gralloc_alloc(alloc_device_t *dev, int w, int h, int format, int usage,
-			      buffer_handle_t *handle, int *stride)
-{
-	auto mod = (struct cros_gralloc_module *)dev->common.module;
-	std::lock_guard<std::mutex> lock(mod->mutex);
-
-	auto bo = cros_gralloc_bo_create(mod->drv, w, h, format, usage);
-	if (!bo)
-		return CROS_GRALLOC_ERROR_NO_RESOURCES;
-
-	auto hnd = cros_gralloc_handle_from_bo(bo->bo);
-	hnd->droid_format = static_cast<int32_t>(format);
-	hnd->usage = static_cast<int32_t>(usage);
-
-	mod->handles[hnd].registrations = 0;
-	mod->handles[hnd].bo = bo;
-	bo->hnd = hnd;
-
-	mod->buffers[drv_bo_get_plane_handle(bo->bo, 0).u32] = bo;
-
-	*stride = static_cast<int>(hnd->pixel_stride);
-	*handle = &hnd->base;
-
-	return CROS_GRALLOC_ERROR_NONE;
-}
-
-static int cros_gralloc_free(alloc_device_t *dev, buffer_handle_t handle)
-{
-	struct cros_gralloc_bo *bo;
-	auto hnd = (struct cros_gralloc_handle *)handle;
-	auto mod = (struct cros_gralloc_module *)dev->common.module;
-	std::lock_guard<std::mutex> lock(mod->mutex);
-
-	if (cros_gralloc_validate_handle(hnd)) {
-		cros_gralloc_error("Invalid handle.");
-		return CROS_GRALLOC_ERROR_BAD_HANDLE;
-	}
-
-	if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
-		cros_gralloc_error("Invalid Reference.");
-		return CROS_GRALLOC_ERROR_BAD_HANDLE;
-	}
-
-	if (mod->handles[hnd].registrations > 0) {
-		cros_gralloc_error("Deallocating before unregistering.");
-		return CROS_GRALLOC_ERROR_BAD_HANDLE;
-	}
-
-	return cros_gralloc_decrement_reference_count(mod, bo);
-}
-
-static int cros_gralloc_close(struct hw_device_t *dev)
-{
-	auto mod = (struct cros_gralloc_module *)dev->module;
-	auto alloc = (struct alloc_device_t *)dev;
-
-	if (mod->drv) {
-		drv_destroy(mod->drv);
-		mod->drv = NULL;
-	}
-
-	mod->buffers.clear();
-	mod->handles.clear();
-
-	delete alloc;
-
-	return CROS_GRALLOC_ERROR_NONE;
-}
-
-int cros_gralloc_open(const struct hw_module_t *mod, const char *name, struct hw_device_t **dev)
-{
-	auto module = (struct cros_gralloc_module *)mod;
-	std::lock_guard<std::mutex> lock(module->mutex);
-
-	if (module->drv)
-		return CROS_GRALLOC_ERROR_NONE;
-
-	if (strcmp(name, GRALLOC_HARDWARE_GPU0)) {
-		cros_gralloc_error("Incorrect device name - %s.", name);
-		return CROS_GRALLOC_ERROR_UNSUPPORTED;
-	}
-
-	if (cros_gralloc_rendernode_open(&module->drv)) {
-		cros_gralloc_error("Failed to open render node.");
-		return CROS_GRALLOC_ERROR_NO_RESOURCES;
-	}
-
-	auto alloc = new alloc_device_t();
-
-	alloc->alloc = cros_gralloc_alloc;
-	alloc->free = cros_gralloc_free;
-	alloc->common.tag = HARDWARE_DEVICE_TAG;
-	alloc->common.version = 0;
-	alloc->common.module = (hw_module_t *)mod;
-	alloc->common.close = cros_gralloc_close;
-
-	*dev = &alloc->common;
-
-	return CROS_GRALLOC_ERROR_NONE;
-}
diff --git a/cros_gralloc/cros_gralloc.h b/cros_gralloc/cros_gralloc.h
deleted file mode 100644
index deca856..0000000
--- a/cros_gralloc/cros_gralloc.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2016 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GBM_GRALLOC_H
-#define GBM_GRALLOC_H
-
-#include "cros_gralloc_helpers.h"
-
-#include <mutex>
-#include <unordered_map>
-#include <unordered_set>
-
-struct cros_gralloc_bo {
-	struct bo *bo;
-	int32_t refcount;
-	struct cros_gralloc_handle *hnd;
-	struct map_info *map_data;
-	int32_t lockcount;
-};
-
-struct handle_info {
-	cros_gralloc_bo *bo;
-	int32_t registrations;
-};
-
-struct cros_gralloc_module {
-	gralloc_module_t base;
-	struct driver *drv;
-	std::mutex mutex;
-	std::unordered_map<cros_gralloc_handle *, handle_info> handles;
-	std::unordered_map<uint32_t, cros_gralloc_bo *> buffers;
-};
-
-int cros_gralloc_open(const struct hw_module_t *mod, const char *name, struct hw_device_t **dev);
-
-int cros_gralloc_validate_reference(struct cros_gralloc_module *mod,
-				    struct cros_gralloc_handle *hnd, struct cros_gralloc_bo **obj);
-
-int cros_gralloc_decrement_reference_count(struct cros_gralloc_module *mod,
-					   struct cros_gralloc_bo *obj);
-
-#endif
diff --git a/cros_gralloc/cros_gralloc_buffer.cc b/cros_gralloc/cros_gralloc_buffer.cc
new file mode 100644
index 0000000..1ef7278
--- /dev/null
+++ b/cros_gralloc/cros_gralloc_buffer.cc
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2017 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "cros_gralloc_buffer.h"
+
+#include <assert.h>
+#include <sys/mman.h>
+
+cros_gralloc_buffer::cros_gralloc_buffer(uint32_t id, struct bo *acquirebo_,
+					 struct cros_gralloc_handle *acquire_handle)
+    : id_(id), bo_(acquirebo_), hnd_(acquire_handle), refcount_(1), lockcount_(0)
+{
+	assert(bo_);
+	num_planes_ = drv_bo_get_num_planes(bo_);
+	for (uint32_t plane = 0; plane < num_planes_; plane++)
+		lock_data_[plane] = nullptr;
+}
+
+cros_gralloc_buffer::~cros_gralloc_buffer()
+{
+	drv_bo_destroy(bo_);
+	if (hnd_) {
+		native_handle_close(&hnd_->base);
+		delete hnd_;
+	}
+}
+
+uint32_t cros_gralloc_buffer::get_id() const
+{
+	return id_;
+}
+
+int32_t cros_gralloc_buffer::increase_refcount()
+{
+	return ++refcount_;
+}
+
+int32_t cros_gralloc_buffer::decrease_refcount()
+{
+	assert(refcount_ > 0);
+	return --refcount_;
+}
+
+int32_t cros_gralloc_buffer::lock(uint64_t flags, uint8_t *addr[DRV_MAX_PLANES])
+{
+	/*
+	 * Gralloc consumers don't support more than one kernel buffer per buffer object yet, so
+	 * just use the first kernel buffer.
+	 */
+	if (drv_num_buffers_per_bo(bo_) != 1) {
+		cros_gralloc_error("Can only support one buffer per bo.");
+		return CROS_GRALLOC_ERROR_NO_RESOURCES;
+	}
+
+	if (flags) {
+		void *vaddr;
+		if (lock_data_[0]) {
+			vaddr = lock_data_[0]->addr;
+		} else {
+			vaddr = drv_bo_map(bo_, 0, 0, drv_bo_get_width(bo_), drv_bo_get_height(bo_),
+					   0, &lock_data_[0], 0);
+		}
+
+		if (vaddr == MAP_FAILED) {
+			cros_gralloc_error("Mapping failed.");
+			return CROS_GRALLOC_ERROR_UNSUPPORTED;
+		}
+
+		addr[0] = static_cast<uint8_t *>(vaddr);
+	}
+
+	for (uint32_t plane = 0; plane < num_planes_; plane++)
+		addr[plane] = addr[0] + drv_bo_get_plane_offset(bo_, plane);
+
+	lockcount_++;
+	return CROS_GRALLOC_ERROR_NONE;
+}
+
+int32_t cros_gralloc_buffer::unlock()
+{
+	if (lockcount_ <= 0) {
+		cros_gralloc_error("Buffer was not locked.");
+		return CROS_GRALLOC_ERROR_UNSUPPORTED;
+	}
+
+	if (!--lockcount_) {
+		if (lock_data_[0]) {
+			drv_bo_unmap(bo_, lock_data_[0]);
+			lock_data_[0] = nullptr;
+		}
+	}
+
+	return CROS_GRALLOC_ERROR_NONE;
+}
diff --git a/cros_gralloc/cros_gralloc_buffer.h b/cros_gralloc/cros_gralloc_buffer.h
new file mode 100644
index 0000000..673ff9d
--- /dev/null
+++ b/cros_gralloc/cros_gralloc_buffer.h
@@ -0,0 +1,44 @@
+/*
+ * 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_BUFFER_H
+#define CROS_GRALLOC_BUFFER_H
+
+#include "../drv.h"
+#include "cros_gralloc_helpers.h"
+
+class cros_gralloc_buffer
+{
+      public:
+	cros_gralloc_buffer(uint32_t id, struct bo *acquirebo_,
+			    struct cros_gralloc_handle *acquire_handle);
+	~cros_gralloc_buffer();
+
+	uint32_t get_id() const;
+
+	/* The new reference count is returned by both these functions. */
+	int32_t increase_refcount();
+	int32_t decrease_refcount();
+
+	int32_t lock(uint64_t flags, uint8_t *addr[DRV_MAX_PLANES]);
+	int32_t unlock();
+
+      private:
+	cros_gralloc_buffer(cros_gralloc_buffer const &);
+	cros_gralloc_buffer operator=(cros_gralloc_buffer const &);
+
+	uint32_t id_;
+	struct bo *bo_;
+	struct cros_gralloc_handle *hnd_;
+
+	int32_t refcount_;
+	int32_t lockcount_;
+	uint32_t num_planes_;
+
+	struct map_info *lock_data_[DRV_MAX_PLANES];
+};
+
+#endif
diff --git a/cros_gralloc/cros_gralloc_driver.cc b/cros_gralloc/cros_gralloc_driver.cc
new file mode 100644
index 0000000..603e96d
--- /dev/null
+++ b/cros_gralloc/cros_gralloc_driver.cc
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2017 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "cros_gralloc_driver.h"
+#include "../util.h"
+
+#include <cstdlib>
+#include <fcntl.h>
+#include <xf86drm.h>
+
+cros_gralloc_driver::cros_gralloc_driver() : drv_(nullptr)
+{
+}
+
+cros_gralloc_driver::~cros_gralloc_driver()
+{
+	buffers_.clear();
+	handles_.clear();
+
+	if (drv_) {
+		drv_destroy(drv_);
+		drv_ = nullptr;
+	}
+}
+
+int32_t cros_gralloc_driver::init()
+{
+	/*
+	 * Create a driver from rendernode while filtering out
+	 * the specified undesired driver.
+	 *
+	 * TODO(gsingh): Enable render nodes on udl/evdi.
+	 */
+
+	int fd;
+	drmVersionPtr version;
+	char const *str = "%s/renderD%d";
+	const char *undesired[2] = { "vgem", nullptr };
+	uint32_t num_nodes = 63;
+	uint32_t min_node = 128;
+	uint32_t max_node = (min_node + num_nodes);
+
+	for (uint32_t i = 0; i < ARRAY_SIZE(undesired); i++) {
+		for (uint32_t j = min_node; j < max_node; j++) {
+			char *node;
+			if (asprintf(&node, str, DRM_DIR_NAME, j) < 0)
+				continue;
+
+			fd = open(node, O_RDWR, 0);
+			free(node);
+
+			if (fd < 0)
+				continue;
+
+			version = drmGetVersion(fd);
+			if (!version)
+				continue;
+
+			if (undesired[i] && !strcmp(version->name, undesired[i])) {
+				drmFreeVersion(version);
+				continue;
+			}
+
+			drmFreeVersion(version);
+			drv_ = drv_create(fd);
+			if (drv_)
+				return CROS_GRALLOC_ERROR_NONE;
+		}
+	}
+
+	return CROS_GRALLOC_ERROR_NO_RESOURCES;
+}
+
+bool cros_gralloc_driver::is_supported(const struct cros_gralloc_buffer_descriptor *descriptor)
+{
+	struct combination *combo;
+	combo = drv_get_combination(drv_, drv_resolve_format(drv_, descriptor->drm_format),
+				    descriptor->drv_usage);
+	return (combo != nullptr);
+}
+
+int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descriptor *descriptor,
+				      buffer_handle_t *out_handle)
+{
+	uint32_t id;
+	uint64_t mod;
+	size_t num_planes;
+
+	struct bo *bo;
+	struct cros_gralloc_handle *hnd;
+
+	bo = drv_bo_create(drv_, descriptor->width, descriptor->height,
+			   drv_resolve_format(drv_, descriptor->drm_format), descriptor->drv_usage);
+	if (!bo) {
+		cros_gralloc_error("Failed to create bo.");
+		return CROS_GRALLOC_ERROR_NO_RESOURCES;
+	}
+
+	/*
+	 * If there is a desire for more than one kernel buffer, this can be
+	 * removed once the ArcCodec and Wayland service have the ability to
+	 * send more than one fd. GL/Vulkan drivers may also have to modified.
+	 */
+	if (drv_num_buffers_per_bo(bo) != 1) {
+		drv_bo_destroy(bo);
+		cros_gralloc_error("Can only support one buffer per bo.");
+		return CROS_GRALLOC_ERROR_NO_RESOURCES;
+	}
+
+	hnd = new cros_gralloc_handle();
+	num_planes = drv_bo_get_num_planes(bo);
+
+	hnd->base.version = sizeof(hnd->base);
+	hnd->base.numFds = num_planes;
+	hnd->base.numInts = handle_data_size - num_planes;
+
+	for (size_t plane = 0; plane < num_planes; plane++) {
+		hnd->fds[plane] = drv_bo_get_plane_fd(bo, plane);
+		hnd->strides[plane] = drv_bo_get_plane_stride(bo, plane);
+		hnd->offsets[plane] = drv_bo_get_plane_offset(bo, plane);
+		hnd->sizes[plane] = drv_bo_get_plane_size(bo, plane);
+
+		mod = drv_bo_get_plane_format_modifier(bo, plane);
+		hnd->format_modifiers[2 * plane] = static_cast<uint32_t>(mod >> 32);
+		hnd->format_modifiers[2 * plane + 1] = static_cast<uint32_t>(mod);
+	}
+
+	hnd->width = drv_bo_get_width(bo);
+	hnd->height = drv_bo_get_height(bo);
+	hnd->format = drv_bo_get_format(bo);
+	hnd->pixel_stride = drv_bo_get_stride_in_pixels(bo);
+	hnd->magic = cros_gralloc_magic;
+	hnd->droid_format = descriptor->droid_format;
+	hnd->usage = descriptor->producer_usage;
+
+	id = drv_bo_get_plane_handle(bo, 0).u32;
+	auto buffer = new cros_gralloc_buffer(id, bo, hnd);
+
+	std::lock_guard<std::mutex> lock(mutex_);
+	buffers_.emplace(id, buffer);
+	handles_.emplace(hnd, std::make_pair(buffer, 1));
+	*out_handle = &hnd->base;
+	return CROS_GRALLOC_ERROR_NONE;
+}
+
+int32_t cros_gralloc_driver::retain(buffer_handle_t handle)
+{
+	uint32_t id;
+	std::lock_guard<std::mutex> lock(mutex_);
+
+	auto hnd = cros_gralloc_convert_handle(handle);
+	if (!hnd) {
+		cros_gralloc_error("Invalid handle.");
+		return CROS_GRALLOC_ERROR_BAD_HANDLE;
+	}
+
+	auto buffer = get_buffer(hnd);
+	if (buffer) {
+		handles_[hnd].second++;
+		buffer->increase_refcount();
+		return CROS_GRALLOC_ERROR_NONE;
+	}
+
+	if (drmPrimeFDToHandle(drv_get_fd(drv_), hnd->fds[0], &id)) {
+		cros_gralloc_error("drmPrimeFDToHandle failed.");
+		return CROS_GRALLOC_ERROR_BAD_HANDLE;
+	}
+
+	if (buffers_.count(id)) {
+		buffer = buffers_[id];
+		buffer->increase_refcount();
+	} else {
+		struct bo *bo;
+		struct drv_import_fd_data data;
+		data.format = hnd->format;
+		data.width = hnd->width;
+		data.height = hnd->height;
+
+		memcpy(data.fds, hnd->fds, sizeof(data.fds));
+		memcpy(data.strides, hnd->strides, sizeof(data.strides));
+		memcpy(data.offsets, hnd->offsets, sizeof(data.offsets));
+		memcpy(data.sizes, hnd->sizes, sizeof(data.sizes));
+		for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++) {
+			data.format_modifiers[plane] =
+			    static_cast<uint64_t>(hnd->format_modifiers[2 * plane]) << 32;
+			data.format_modifiers[plane] |= hnd->format_modifiers[2 * plane + 1];
+		}
+
+		bo = drv_bo_import(drv_, &data);
+		if (!bo)
+			return CROS_GRALLOC_ERROR_NO_RESOURCES;
+
+		id = drv_bo_get_plane_handle(bo, 0).u32;
+
+		buffer = new cros_gralloc_buffer(id, bo, nullptr);
+		buffers_.emplace(id, buffer);
+	}
+
+	handles_.emplace(hnd, std::make_pair(buffer, 1));
+	return CROS_GRALLOC_ERROR_NONE;
+}
+
+int32_t cros_gralloc_driver::release(buffer_handle_t handle)
+{
+	std::lock_guard<std::mutex> lock(mutex_);
+
+	auto hnd = cros_gralloc_convert_handle(handle);
+	if (!hnd) {
+		cros_gralloc_error("Invalid handle.");
+		return CROS_GRALLOC_ERROR_BAD_HANDLE;
+	}
+
+	auto buffer = get_buffer(hnd);
+	if (!buffer) {
+		cros_gralloc_error("Invalid Reference.");
+		return CROS_GRALLOC_ERROR_BAD_HANDLE;
+	}
+
+	if (!--handles_[hnd].second)
+		handles_.erase(hnd);
+
+	if (buffer->decrease_refcount() == 0) {
+		buffers_.erase(buffer->get_id());
+		delete buffer;
+	}
+
+	return CROS_GRALLOC_ERROR_NONE;
+}
+
+int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence, uint64_t flags,
+				  uint8_t *addr[DRV_MAX_PLANES])
+{
+	std::lock_guard<std::mutex> lock(mutex_);
+
+	auto hnd = cros_gralloc_convert_handle(handle);
+	if (!hnd) {
+		cros_gralloc_error("Invalid handle.");
+		return CROS_GRALLOC_ERROR_BAD_HANDLE;
+	}
+
+	auto buffer = get_buffer(hnd);
+	if (!buffer) {
+		cros_gralloc_error("Invalid Reference.");
+		return CROS_GRALLOC_ERROR_BAD_HANDLE;
+	}
+
+	if (acquire_fence >= 0) {
+		cros_gralloc_error("Sync wait not yet supported.");
+		return CROS_GRALLOC_ERROR_UNSUPPORTED;
+	}
+
+	return buffer->lock(flags, addr);
+}
+
+int32_t cros_gralloc_driver::unlock(buffer_handle_t handle)
+{
+	std::lock_guard<std::mutex> lock(mutex_);
+
+	auto hnd = cros_gralloc_convert_handle(handle);
+	if (!hnd) {
+		cros_gralloc_error("Invalid handle.");
+		return CROS_GRALLOC_ERROR_BAD_HANDLE;
+	}
+
+	auto buffer = get_buffer(hnd);
+	if (!buffer) {
+		cros_gralloc_error("Invalid Reference.");
+		return CROS_GRALLOC_ERROR_BAD_HANDLE;
+	}
+
+	return buffer->unlock();
+}
+
+int32_t cros_gralloc_driver::get_backing_store(buffer_handle_t handle, uint64_t *out_store)
+{
+	std::lock_guard<std::mutex> lock(mutex_);
+
+	auto hnd = cros_gralloc_convert_handle(handle);
+	if (!hnd) {
+		cros_gralloc_error("Invalid handle.");
+		return CROS_GRALLOC_ERROR_BAD_HANDLE;
+	}
+
+	auto buffer = get_buffer(hnd);
+	if (!buffer) {
+		cros_gralloc_error("Invalid Reference.");
+		return CROS_GRALLOC_ERROR_BAD_HANDLE;
+	}
+
+	*out_store = static_cast<uint64_t>(buffer->get_id());
+	return CROS_GRALLOC_ERROR_NONE;
+}
+
+cros_gralloc_buffer *cros_gralloc_driver::get_buffer(cros_gralloc_handle_t hnd)
+{
+	/* Assumes driver mutex is held. */
+	if (handles_.count(hnd))
+		return handles_[hnd].first;
+
+	return nullptr;
+}
diff --git a/cros_gralloc/cros_gralloc_driver.h b/cros_gralloc/cros_gralloc_driver.h
new file mode 100644
index 0000000..7b3b668
--- /dev/null
+++ b/cros_gralloc/cros_gralloc_driver.h
@@ -0,0 +1,47 @@
+/*
+ * 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_DRIVER_H
+#define CROS_GRALLOC_DRIVER_H
+
+#include "cros_gralloc_buffer.h"
+
+#include <mutex>
+#include <unordered_map>
+
+class cros_gralloc_driver
+{
+      public:
+	cros_gralloc_driver();
+	~cros_gralloc_driver();
+
+	int32_t init();
+	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);
+
+	int32_t retain(buffer_handle_t handle);
+	int32_t release(buffer_handle_t handle);
+
+	int32_t lock(buffer_handle_t handle, int32_t acquire_fence, uint64_t flags,
+		     uint8_t *addr[DRV_MAX_PLANES]);
+	int32_t unlock(buffer_handle_t handle);
+
+	int32_t get_backing_store(buffer_handle_t handle, uint64_t *out_store);
+
+      private:
+	cros_gralloc_driver(cros_gralloc_driver const &);
+	cros_gralloc_driver operator=(cros_gralloc_driver const &);
+	cros_gralloc_buffer *get_buffer(cros_gralloc_handle_t hnd);
+
+	struct driver *drv_;
+	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>>
+	    handles_;
+};
+
+#endif
diff --git a/cros_gralloc/cros_gralloc_handle.h b/cros_gralloc/cros_gralloc_handle.h
index e2c0bcc..e549675 100644
--- a/cros_gralloc/cros_gralloc_handle.h
+++ b/cros_gralloc/cros_gralloc_handle.h
@@ -33,4 +33,6 @@
 	int32_t usage; /* Android usage. */
 };
 
+typedef const struct cros_gralloc_handle *cros_gralloc_handle_t;
+
 #endif
diff --git a/cros_gralloc/cros_gralloc_helpers.cc b/cros_gralloc/cros_gralloc_helpers.cc
index 6504b10..f0b667d 100644
--- a/cros_gralloc/cros_gralloc_helpers.cc
+++ b/cros_gralloc/cros_gralloc_helpers.cc
@@ -8,54 +8,6 @@
 
 #include <cstdlib>
 #include <cutils/log.h>
-#include <fcntl.h>
-#include <xf86drm.h>
-
-uint64_t cros_gralloc_convert_flags(int flags)
-{
-	uint64_t usage = BO_USE_NONE;
-
-	if (flags & GRALLOC_USAGE_CURSOR)
-		usage |= BO_USE_NONE;
-	if ((flags & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_RARELY)
-		usage |= BO_USE_SW_READ_RARELY;
-	if ((flags & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN)
-		usage |= BO_USE_SW_READ_OFTEN;
-	if ((flags & GRALLOC_USAGE_SW_WRITE_MASK) == GRALLOC_USAGE_SW_WRITE_RARELY)
-		usage |= BO_USE_SW_WRITE_RARELY;
-	if ((flags & GRALLOC_USAGE_SW_WRITE_MASK) == GRALLOC_USAGE_SW_WRITE_OFTEN)
-		usage |= BO_USE_SW_WRITE_OFTEN;
-	if (flags & GRALLOC_USAGE_HW_TEXTURE)
-		usage |= BO_USE_TEXTURE;
-	if (flags & GRALLOC_USAGE_HW_RENDER)
-		usage |= BO_USE_RENDERING;
-	if (flags & GRALLOC_USAGE_HW_2D)
-		usage |= BO_USE_RENDERING;
-	if (flags & GRALLOC_USAGE_HW_COMPOSER)
-		/* HWC wants to use display hardware, but can defer to OpenGL. */
-		usage |= BO_USE_SCANOUT | BO_USE_TEXTURE;
-	if (flags & GRALLOC_USAGE_HW_FB)
-		usage |= BO_USE_NONE;
-	if (flags & GRALLOC_USAGE_EXTERNAL_DISP)
-		/* We're ignoring this flag until we decide what to with display link */
-		usage |= BO_USE_NONE;
-	if (flags & GRALLOC_USAGE_PROTECTED)
-		usage |= BO_USE_PROTECTED;
-	if (flags & GRALLOC_USAGE_HW_VIDEO_ENCODER)
-		/*HACK: See b/30054495 */
-		usage |= BO_USE_SW_READ_OFTEN;
-	if (flags & GRALLOC_USAGE_HW_CAMERA_WRITE)
-		usage |= BO_USE_HW_CAMERA_WRITE;
-	if (flags & GRALLOC_USAGE_HW_CAMERA_READ)
-		usage |= BO_USE_HW_CAMERA_READ;
-	if (flags & GRALLOC_USAGE_HW_CAMERA_ZSL)
-		usage |= BO_USE_HW_CAMERA_ZSL;
-	if (flags & GRALLOC_USAGE_RENDERSCRIPT)
-		/* We use CPU for compute. */
-		usage |= BO_USE_LINEAR;
-
-	return usage;
-}
 
 uint32_t cros_gralloc_convert_format(int format)
 {
@@ -93,71 +45,13 @@
 	return DRM_FORMAT_NONE;
 }
 
-static int32_t cros_gralloc_query_rendernode(struct driver **drv, const char *undesired)
+cros_gralloc_handle_t cros_gralloc_convert_handle(buffer_handle_t handle)
 {
-	/*
-	 * Create a driver from rendernode while filtering out
-	 * the specified undesired driver.
-	 *
-	 * TODO(gsingh): Enable render nodes on udl/evdi.
-	 */
-
-	int fd;
-	drmVersionPtr version;
-	char const *str = "%s/renderD%d";
-	int32_t num_nodes = 63;
-	int32_t min_node = 128;
-	int32_t max_node = (min_node + num_nodes);
-
-	for (int i = min_node; i < max_node; i++) {
-		char *node;
-
-		if (asprintf(&node, str, DRM_DIR_NAME, i) < 0)
-			continue;
-
-		fd = open(node, O_RDWR, 0);
-		free(node);
-
-		if (fd < 0)
-			continue;
-
-		version = drmGetVersion(fd);
-		if (!version)
-			continue;
-
-		if (undesired && !strcmp(version->name, undesired)) {
-			drmFreeVersion(version);
-			continue;
-		}
-
-		drmFreeVersion(version);
-		*drv = drv_create(fd);
-
-		if (*drv)
-			return CROS_GRALLOC_ERROR_NONE;
-	}
-
-	return CROS_GRALLOC_ERROR_NO_RESOURCES;
-}
-
-int32_t cros_gralloc_rendernode_open(struct driver **drv)
-{
-	int32_t ret;
-	ret = cros_gralloc_query_rendernode(drv, "vgem");
-
-	/* Allow vgem driver if no hardware is found. */
-	if (ret)
-		ret = cros_gralloc_query_rendernode(drv, NULL);
-
-	return ret;
-}
-
-int32_t cros_gralloc_validate_handle(struct cros_gralloc_handle *hnd)
-{
+	auto hnd = reinterpret_cast<cros_gralloc_handle_t>(handle);
 	if (!hnd || hnd->magic != cros_gralloc_magic)
-		return CROS_GRALLOC_ERROR_BAD_HANDLE;
+		return nullptr;
 
-	return CROS_GRALLOC_ERROR_NONE;
+	return hnd;
 }
 
 void cros_gralloc_log(const char *prefix, const char *file, int line, const char *format, ...)
diff --git a/cros_gralloc/cros_gralloc_helpers.h b/cros_gralloc/cros_gralloc_helpers.h
index 457fcac..f198dd9 100644
--- a/cros_gralloc/cros_gralloc_helpers.h
+++ b/cros_gralloc/cros_gralloc_helpers.h
@@ -9,55 +9,19 @@
 
 #include "../drv.h"
 #include "cros_gralloc_handle.h"
+#include "cros_gralloc_types.h"
 
-#include <hardware/gralloc.h>
 #include <system/graphics.h>
-
-/* Use these error codes derived from gralloc1 to make transition easier when
- * it happens
- */
-typedef enum {
-	CROS_GRALLOC_ERROR_NONE = 0,
-	CROS_GRALLOC_ERROR_BAD_DESCRIPTOR = 1,
-	CROS_GRALLOC_ERROR_BAD_HANDLE = 2,
-	CROS_GRALLOC_ERROR_BAD_VALUE = 3,
-	CROS_GRALLOC_ERROR_NOT_SHARED = 4,
-	CROS_GRALLOC_ERROR_NO_RESOURCES = 5,
-	CROS_GRALLOC_ERROR_UNDEFINED = 6,
-	CROS_GRALLOC_ERROR_UNSUPPORTED = 7,
-} cros_gralloc_error_t;
-
-/* This enumeration must match the one in <gralloc_drm.h>.
- * The functions supported by this gralloc's temporary private API are listed
- * below. Use of these functions is highly discouraged and should only be
- * reserved for cases where no alternative to get same information (such as
- * querying ANativeWindow) exists.
- */
-// clang-format off
-enum {
-	GRALLOC_DRM_GET_STRIDE,
-	GRALLOC_DRM_GET_FORMAT,
-	GRALLOC_DRM_GET_DIMENSIONS,
-	GRALLOC_DRM_GET_BACKING_STORE,
-};
-// clang-format on
+#include <system/window.h>
 
 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));
 
-constexpr uint32_t sw_access = GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK;
+uint32_t cros_gralloc_convert_format(int32_t format);
 
-uint64_t cros_gralloc_convert_flags(int flags);
+cros_gralloc_handle_t cros_gralloc_convert_handle(buffer_handle_t handle);
 
-uint32_t cros_gralloc_convert_format(int format);
-
-int32_t cros_gralloc_rendernode_open(struct driver **drv);
-
-int32_t cros_gralloc_validate_handle(struct cros_gralloc_handle *hnd);
-
-/* Logging code adapted from bsdrm */
 __attribute__((format(printf, 4, 5))) void cros_gralloc_log(const char *prefix, const char *file,
 							    int line, const char *format, ...);
 
diff --git a/cros_gralloc/cros_gralloc_module.cc b/cros_gralloc/cros_gralloc_module.cc
deleted file mode 100644
index bbe3c6f..0000000
--- a/cros_gralloc/cros_gralloc_module.cc
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * Copyright 2016 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "cros_gralloc.h"
-
-#include <sys/mman.h>
-#include <xf86drm.h>
-
-int cros_gralloc_validate_reference(struct cros_gralloc_module *mod,
-				    struct cros_gralloc_handle *hnd, struct cros_gralloc_bo **bo)
-{
-	if (!mod->handles.count(hnd))
-		return CROS_GRALLOC_ERROR_BAD_HANDLE;
-
-	*bo = mod->handles[hnd].bo;
-	return CROS_GRALLOC_ERROR_NONE;
-}
-
-int cros_gralloc_decrement_reference_count(struct cros_gralloc_module *mod,
-					   struct cros_gralloc_bo *bo)
-{
-	if (bo->refcount <= 0) {
-		cros_gralloc_error("The reference count is <= 0.");
-		assert(0);
-	}
-
-	if (!--bo->refcount) {
-		mod->buffers.erase(drv_bo_get_plane_handle(bo->bo, 0).u32);
-		drv_bo_destroy(bo->bo);
-
-		if (bo->hnd) {
-			mod->handles.erase(bo->hnd);
-			native_handle_close(&bo->hnd->base);
-			delete bo->hnd;
-		}
-
-		delete bo;
-	}
-
-	return CROS_GRALLOC_ERROR_NONE;
-}
-
-static int cros_gralloc_register_buffer(struct gralloc_module_t const *module,
-					buffer_handle_t handle)
-{
-	uint32_t id;
-	struct cros_gralloc_bo *bo;
-	auto hnd = (struct cros_gralloc_handle *)handle;
-	auto mod = (struct cros_gralloc_module *)module;
-	std::lock_guard<std::mutex> lock(mod->mutex);
-
-	if (cros_gralloc_validate_handle(hnd)) {
-		cros_gralloc_error("Invalid handle.");
-		return CROS_GRALLOC_ERROR_BAD_HANDLE;
-	}
-
-	if (!mod->drv) {
-		if (cros_gralloc_rendernode_open(&mod->drv)) {
-			cros_gralloc_error("Failed to open render node.");
-			return CROS_GRALLOC_ERROR_NO_RESOURCES;
-		}
-	}
-
-	if (!cros_gralloc_validate_reference(mod, hnd, &bo)) {
-		bo->refcount++;
-		mod->handles[hnd].registrations++;
-		return CROS_GRALLOC_ERROR_NONE;
-	}
-
-	if (drmPrimeFDToHandle(drv_get_fd(mod->drv), hnd->fds[0], &id)) {
-		cros_gralloc_error("drmPrimeFDToHandle failed.");
-		return CROS_GRALLOC_ERROR_BAD_HANDLE;
-	}
-
-	if (mod->buffers.count(id)) {
-		bo = mod->buffers[id];
-		bo->refcount++;
-	} else {
-		struct drv_import_fd_data data;
-		data.format = hnd->format;
-		data.width = hnd->width;
-		data.height = hnd->height;
-
-		memcpy(data.fds, hnd->fds, sizeof(data.fds));
-		memcpy(data.strides, hnd->strides, sizeof(data.strides));
-		memcpy(data.offsets, hnd->offsets, sizeof(data.offsets));
-		memcpy(data.sizes, hnd->sizes, sizeof(data.sizes));
-		for (uint32_t p = 0; p < DRV_MAX_PLANES; p++) {
-			data.format_modifiers[p] =
-			    static_cast<uint64_t>(hnd->format_modifiers[2 * p]) << 32;
-			data.format_modifiers[p] |= hnd->format_modifiers[2 * p + 1];
-		}
-
-		bo = new cros_gralloc_bo();
-		bo->bo = drv_bo_import(mod->drv, &data);
-		if (!bo->bo) {
-			delete bo;
-			return CROS_GRALLOC_ERROR_NO_RESOURCES;
-		}
-
-		id = drv_bo_get_plane_handle(bo->bo, 0).u32;
-		mod->buffers[id] = bo;
-
-		bo->refcount = 1;
-	}
-
-	mod->handles[hnd].bo = bo;
-	mod->handles[hnd].registrations = 1;
-
-	return CROS_GRALLOC_ERROR_NONE;
-}
-
-static int cros_gralloc_unregister_buffer(struct gralloc_module_t const *module,
-					  buffer_handle_t handle)
-{
-	struct cros_gralloc_bo *bo;
-	auto hnd = (struct cros_gralloc_handle *)handle;
-	auto mod = (struct cros_gralloc_module *)module;
-	std::lock_guard<std::mutex> lock(mod->mutex);
-
-	if (cros_gralloc_validate_handle(hnd)) {
-		cros_gralloc_error("Invalid handle.");
-		return CROS_GRALLOC_ERROR_BAD_HANDLE;
-	}
-
-	if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
-		cros_gralloc_error("Invalid Reference.");
-		return CROS_GRALLOC_ERROR_BAD_HANDLE;
-	}
-
-	if (mod->handles[hnd].registrations <= 0) {
-		cros_gralloc_error("Handle not registered.");
-		return CROS_GRALLOC_ERROR_BAD_HANDLE;
-	}
-
-	mod->handles[hnd].registrations--;
-
-	if (!mod->handles[hnd].registrations)
-		mod->handles.erase(hnd);
-
-	return cros_gralloc_decrement_reference_count(mod, bo);
-}
-
-static int cros_gralloc_lock(struct gralloc_module_t const *module, buffer_handle_t handle,
-			     int usage, int l, int t, int w, int h, void **vaddr)
-{
-	struct cros_gralloc_bo *bo;
-	auto mod = (struct cros_gralloc_module *)module;
-	auto hnd = (struct cros_gralloc_handle *)handle;
-	std::lock_guard<std::mutex> lock(mod->mutex);
-
-	if (cros_gralloc_validate_handle(hnd)) {
-		cros_gralloc_error("Invalid handle.");
-		return CROS_GRALLOC_ERROR_BAD_HANDLE;
-	}
-
-	if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
-		cros_gralloc_error("Invalid Reference.");
-		return CROS_GRALLOC_ERROR_BAD_HANDLE;
-	}
-
-	if ((hnd->droid_format == HAL_PIXEL_FORMAT_YCbCr_420_888)) {
-		cros_gralloc_error("HAL_PIXEL_FORMAT_YCbCr_*_888 format not compatible.");
-		return CROS_GRALLOC_ERROR_BAD_HANDLE;
-	}
-
-	if (sw_access & usage) {
-		if (bo->map_data) {
-			*vaddr = bo->map_data->addr;
-		} else {
-			*vaddr = drv_bo_map(bo->bo, 0, 0, drv_bo_get_width(bo->bo),
-					    drv_bo_get_height(bo->bo), 0, &bo->map_data, 0);
-		}
-
-		if (*vaddr == MAP_FAILED) {
-			cros_gralloc_error("Mapping failed.");
-			return CROS_GRALLOC_ERROR_UNSUPPORTED;
-		}
-	}
-
-	bo->lockcount++;
-
-	return CROS_GRALLOC_ERROR_NONE;
-}
-
-static int cros_gralloc_unlock(struct gralloc_module_t const *module, buffer_handle_t handle)
-{
-	struct cros_gralloc_bo *bo;
-	auto hnd = (struct cros_gralloc_handle *)handle;
-	auto mod = (struct cros_gralloc_module *)module;
-	std::lock_guard<std::mutex> lock(mod->mutex);
-
-	if (cros_gralloc_validate_handle(hnd)) {
-		cros_gralloc_error("Invalid handle.");
-		return CROS_GRALLOC_ERROR_BAD_HANDLE;
-	}
-
-	if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
-		cros_gralloc_error("Invalid Reference.");
-		return CROS_GRALLOC_ERROR_BAD_HANDLE;
-	}
-
-	if (!--bo->lockcount && bo->map_data) {
-		drv_bo_unmap(bo->bo, bo->map_data);
-		bo->map_data = NULL;
-	}
-
-	return CROS_GRALLOC_ERROR_NONE;
-}
-
-static int cros_gralloc_perform(struct gralloc_module_t const *module, int op, ...)
-{
-	va_list args;
-	struct cros_gralloc_bo *bo;
-	int32_t *out_format;
-	uint64_t *out_store;
-	buffer_handle_t handle;
-	uint32_t *out_width, *out_height, *out_stride;
-	auto mod = (struct cros_gralloc_module *)module;
-	std::lock_guard<std::mutex> lock(mod->mutex);
-
-	switch (op) {
-	case GRALLOC_DRM_GET_STRIDE:
-	case GRALLOC_DRM_GET_FORMAT:
-	case GRALLOC_DRM_GET_DIMENSIONS:
-	case GRALLOC_DRM_GET_BACKING_STORE:
-		break;
-	default:
-		return CROS_GRALLOC_ERROR_UNSUPPORTED;
-	}
-
-	va_start(args, op);
-	handle = va_arg(args, buffer_handle_t);
-	auto hnd = (struct cros_gralloc_handle *)handle;
-
-	if (cros_gralloc_validate_handle(hnd)) {
-		cros_gralloc_error("Invalid handle.");
-		return CROS_GRALLOC_ERROR_BAD_HANDLE;
-	}
-
-	if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
-		cros_gralloc_error("Invalid Reference.");
-		return CROS_GRALLOC_ERROR_BAD_HANDLE;
-	}
-
-	switch (op) {
-	case GRALLOC_DRM_GET_STRIDE:
-		out_stride = va_arg(args, uint32_t *);
-		*out_stride = hnd->pixel_stride;
-		break;
-	case GRALLOC_DRM_GET_FORMAT:
-		out_format = va_arg(args, int32_t *);
-		*out_format = hnd->droid_format;
-		break;
-	case GRALLOC_DRM_GET_DIMENSIONS:
-		out_width = va_arg(args, uint32_t *);
-		out_height = va_arg(args, uint32_t *);
-		*out_width = hnd->width;
-		*out_height = hnd->height;
-		break;
-	case GRALLOC_DRM_GET_BACKING_STORE:
-		out_store = va_arg(args, uint64_t *);
-		*out_store = drv_bo_get_plane_handle(bo->bo, 0).u64;
-		break;
-	default:
-		return CROS_GRALLOC_ERROR_UNSUPPORTED;
-	}
-
-	va_end(args);
-
-	return CROS_GRALLOC_ERROR_NONE;
-}
-
-static int cros_gralloc_lock_ycbcr(struct gralloc_module_t const *module, buffer_handle_t handle,
-				   int usage, int l, int t, int w, int h,
-				   struct android_ycbcr *ycbcr)
-{
-	uint8_t *addr = NULL;
-	size_t offsets[DRV_MAX_PLANES];
-	struct cros_gralloc_bo *bo;
-	auto hnd = (struct cros_gralloc_handle *)handle;
-	auto mod = (struct cros_gralloc_module *)module;
-	std::lock_guard<std::mutex> lock(mod->mutex);
-
-	if (cros_gralloc_validate_handle(hnd)) {
-		cros_gralloc_error("Invalid handle.");
-		return CROS_GRALLOC_ERROR_BAD_HANDLE;
-	}
-
-	if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
-		cros_gralloc_error("Invalid Reference.");
-		return CROS_GRALLOC_ERROR_BAD_HANDLE;
-	}
-
-	if ((hnd->droid_format != HAL_PIXEL_FORMAT_YCbCr_420_888) &&
-	    (hnd->droid_format != HAL_PIXEL_FORMAT_YV12)) {
-		cros_gralloc_error("Non-YUV format not compatible.");
-		return CROS_GRALLOC_ERROR_BAD_HANDLE;
-	}
-
-	if (sw_access & usage) {
-		void *vaddr;
-		if (bo->map_data) {
-			vaddr = bo->map_data->addr;
-		} else {
-			vaddr = drv_bo_map(bo->bo, 0, 0, drv_bo_get_width(bo->bo),
-					   drv_bo_get_height(bo->bo), 0, &bo->map_data, 0);
-		}
-
-		if (vaddr == MAP_FAILED) {
-			cros_gralloc_error("Mapping failed.");
-			return CROS_GRALLOC_ERROR_UNSUPPORTED;
-		}
-
-		addr = static_cast<uint8_t *>(vaddr);
-	}
-
-	for (size_t p = 0; p < drv_bo_get_num_planes(bo->bo); p++)
-		offsets[p] = drv_bo_get_plane_offset(bo->bo, p);
-
-	switch (hnd->format) {
-	case DRM_FORMAT_NV12:
-		ycbcr->y = addr;
-		ycbcr->cb = addr + offsets[1];
-		ycbcr->cr = addr + offsets[1] + 1;
-		ycbcr->ystride = drv_bo_get_plane_stride(bo->bo, 0);
-		ycbcr->cstride = drv_bo_get_plane_stride(bo->bo, 1);
-		ycbcr->chroma_step = 2;
-		break;
-	case DRM_FORMAT_YVU420_ANDROID:
-	case DRM_FORMAT_YVU420:
-		ycbcr->y = addr;
-		ycbcr->cb = addr + offsets[2];
-		ycbcr->cr = addr + offsets[1];
-		ycbcr->ystride = drv_bo_get_plane_stride(bo->bo, 0);
-		ycbcr->cstride = drv_bo_get_plane_stride(bo->bo, 1);
-		ycbcr->chroma_step = 1;
-		break;
-	case DRM_FORMAT_UYVY:
-		ycbcr->y = addr + 1;
-		ycbcr->cb = addr;
-		ycbcr->cr = addr + 2;
-		ycbcr->ystride = drv_bo_get_plane_stride(bo->bo, 0);
-		ycbcr->cstride = drv_bo_get_plane_stride(bo->bo, 0);
-		ycbcr->chroma_step = 2;
-		break;
-	default:
-		return CROS_GRALLOC_ERROR_UNSUPPORTED;
-	}
-
-	bo->lockcount++;
-
-	return CROS_GRALLOC_ERROR_NONE;
-}
-
-static struct hw_module_methods_t cros_gralloc_module_methods = {.open = cros_gralloc_open };
-
-struct cros_gralloc_module HAL_MODULE_INFO_SYM = {
-	.base =
-	    {
-		.common =
-		    {
-			.tag = HARDWARE_MODULE_TAG,
-			.module_api_version = GRALLOC_MODULE_API_VERSION_0_2,
-			.hal_api_version = 0,
-			.id = GRALLOC_HARDWARE_MODULE_ID,
-			.name = "CrOS Gralloc",
-			.author = "Chrome OS",
-			.methods = &cros_gralloc_module_methods,
-		    },
-		.registerBuffer = cros_gralloc_register_buffer,
-		.unregisterBuffer = cros_gralloc_unregister_buffer,
-		.lock = cros_gralloc_lock,
-		.unlock = cros_gralloc_unlock,
-		.perform = cros_gralloc_perform,
-		.lock_ycbcr = cros_gralloc_lock_ycbcr,
-	    },
-
-	.drv = NULL,
-};
diff --git a/cros_gralloc/cros_gralloc_types.h b/cros_gralloc/cros_gralloc_types.h
new file mode 100644
index 0000000..b1938c8
--- /dev/null
+++ b/cros_gralloc/cros_gralloc_types.h
@@ -0,0 +1,31 @@
+/*
+ * 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
+
+typedef enum {
+	CROS_GRALLOC_ERROR_NONE = 0,
+	CROS_GRALLOC_ERROR_BAD_DESCRIPTOR = 1,
+	CROS_GRALLOC_ERROR_BAD_HANDLE = 2,
+	CROS_GRALLOC_ERROR_BAD_VALUE = 3,
+	CROS_GRALLOC_ERROR_NOT_SHARED = 4,
+	CROS_GRALLOC_ERROR_NO_RESOURCES = 5,
+	CROS_GRALLOC_ERROR_UNDEFINED = 6,
+	CROS_GRALLOC_ERROR_UNSUPPORTED = 7,
+} cros_gralloc_error_t;
+
+struct cros_gralloc_buffer_descriptor {
+	uint32_t width;
+	uint32_t height;
+	uint32_t consumer_usage;
+	uint32_t producer_usage;
+	uint32_t droid_format;
+	uint32_t drm_format;
+	uint64_t drv_usage;
+};
+
+#endif
diff --git a/cros_gralloc/gralloc0/gralloc0.cc b/cros_gralloc/gralloc0/gralloc0.cc
new file mode 100644
index 0000000..79d1113
--- /dev/null
+++ b/cros_gralloc/gralloc0/gralloc0.cc
@@ -0,0 +1,351 @@
+/*
+ * Copyright 2016 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "../cros_gralloc_driver.h"
+
+#include <hardware/gralloc.h>
+#include <memory.h>
+
+struct gralloc0_module {
+	gralloc_module_t base;
+	std::unique_ptr<alloc_device_t> alloc;
+	std::unique_ptr<cros_gralloc_driver> driver;
+};
+
+/* This enumeration must match the one in <gralloc_drm.h>.
+ * The functions supported by this gralloc's temporary private API are listed
+ * below. Use of these functions is highly discouraged and should only be
+ * reserved for cases where no alternative to get same information (such as
+ * querying ANativeWindow) exists.
+ */
+// clang-format off
+enum {
+	GRALLOC_DRM_GET_STRIDE,
+	GRALLOC_DRM_GET_FORMAT,
+	GRALLOC_DRM_GET_DIMENSIONS,
+	GRALLOC_DRM_GET_BACKING_STORE,
+};
+// clang-format on
+
+static int64_t gralloc0_convert_flags(int flags)
+{
+	uint64_t usage = BO_USE_NONE;
+
+	if (flags & GRALLOC_USAGE_CURSOR)
+		usage |= BO_USE_NONE;
+	if ((flags & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_RARELY)
+		usage |= BO_USE_SW_READ_RARELY;
+	if ((flags & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN)
+		usage |= BO_USE_SW_READ_OFTEN;
+	if ((flags & GRALLOC_USAGE_SW_WRITE_MASK) == GRALLOC_USAGE_SW_WRITE_RARELY)
+		usage |= BO_USE_SW_WRITE_RARELY;
+	if ((flags & GRALLOC_USAGE_SW_WRITE_MASK) == GRALLOC_USAGE_SW_WRITE_OFTEN)
+		usage |= BO_USE_SW_WRITE_OFTEN;
+	if (flags & GRALLOC_USAGE_HW_TEXTURE)
+		usage |= BO_USE_TEXTURE;
+	if (flags & GRALLOC_USAGE_HW_RENDER)
+		usage |= BO_USE_RENDERING;
+	if (flags & GRALLOC_USAGE_HW_2D)
+		usage |= BO_USE_RENDERING;
+	if (flags & GRALLOC_USAGE_HW_COMPOSER)
+		/* HWC wants to use display hardware, but can defer to OpenGL. */
+		usage |= BO_USE_SCANOUT | BO_USE_TEXTURE;
+	if (flags & GRALLOC_USAGE_HW_FB)
+		usage |= BO_USE_NONE;
+	if (flags & 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.
+		 * */
+		usage |= BO_USE_NONE;
+	if (flags & GRALLOC_USAGE_PROTECTED)
+		usage |= BO_USE_PROTECTED;
+	if (flags & GRALLOC_USAGE_HW_VIDEO_ENCODER)
+		/*HACK: See b/30054495 */
+		usage |= BO_USE_SW_READ_OFTEN;
+	if (flags & GRALLOC_USAGE_HW_CAMERA_WRITE)
+		usage |= BO_USE_HW_CAMERA_WRITE;
+	if (flags & GRALLOC_USAGE_HW_CAMERA_READ)
+		usage |= BO_USE_HW_CAMERA_READ;
+	if (flags & GRALLOC_USAGE_HW_CAMERA_ZSL)
+		usage |= BO_USE_HW_CAMERA_ZSL;
+	if (flags & GRALLOC_USAGE_RENDERSCRIPT)
+		/* We use CPU for compute. */
+		usage |= BO_USE_LINEAR;
+
+	return usage;
+}
+
+static int gralloc0_alloc(alloc_device_t *dev, int w, int h, int format, int usage,
+			  buffer_handle_t *handle, int *stride)
+{
+	int32_t ret;
+	bool supported;
+	struct cros_gralloc_buffer_descriptor descriptor;
+	auto mod = (struct gralloc0_module *)dev->common.module;
+
+	descriptor.width = w;
+	descriptor.height = h;
+	descriptor.droid_format = format;
+	descriptor.producer_usage = descriptor.consumer_usage = usage;
+	descriptor.drm_format = cros_gralloc_convert_format(format);
+	descriptor.drv_usage = gralloc0_convert_flags(usage);
+
+	supported = mod->driver->is_supported(&descriptor);
+	if (!supported && (usage & GRALLOC_USAGE_HW_COMPOSER)) {
+		descriptor.drv_usage &= ~BO_USE_SCANOUT;
+		supported = mod->driver->is_supported(&descriptor);
+	}
+
+	if (!supported) {
+		cros_gralloc_error("Unsupported combination -- HAL format: %u, HAL flags: %u, "
+				   "drv_format: %4.4s, drv_flags: %llu",
+				   format, usage, reinterpret_cast<char *>(descriptor.drm_format),
+				   static_cast<unsigned long long>(descriptor.drv_usage));
+		return CROS_GRALLOC_ERROR_UNSUPPORTED;
+	}
+
+	ret = mod->driver->allocate(&descriptor, handle);
+	if (ret)
+		return ret;
+
+	auto hnd = cros_gralloc_convert_handle(*handle);
+	*stride = hnd->pixel_stride;
+
+	return CROS_GRALLOC_ERROR_NONE;
+}
+
+static int gralloc0_free(alloc_device_t *dev, buffer_handle_t handle)
+{
+	auto mod = (struct gralloc0_module *)dev->common.module;
+	return mod->driver->release(handle);
+}
+
+static int gralloc0_close(struct hw_device_t *dev)
+{
+	/* Memory is freed by managed pointers on process close. */
+	return CROS_GRALLOC_ERROR_NONE;
+}
+
+static int gralloc0_open(const struct hw_module_t *mod, const char *name, struct hw_device_t **dev)
+{
+	auto module = (struct gralloc0_module *)mod;
+
+	if (module->alloc) {
+		*dev = &module->alloc->common;
+		return CROS_GRALLOC_ERROR_NONE;
+	}
+
+	if (strcmp(name, GRALLOC_HARDWARE_GPU0)) {
+		cros_gralloc_error("Incorrect device name - %s.", name);
+		return CROS_GRALLOC_ERROR_UNSUPPORTED;
+	}
+
+	module->driver = std::make_unique<cros_gralloc_driver>();
+	if (module->driver->init()) {
+		cros_gralloc_error("Failed to initialize driver.");
+		return CROS_GRALLOC_ERROR_NO_RESOURCES;
+	}
+
+	module->alloc = std::make_unique<alloc_device_t>();
+
+	module->alloc->alloc = gralloc0_alloc;
+	module->alloc->free = gralloc0_free;
+	module->alloc->common.tag = HARDWARE_DEVICE_TAG;
+	module->alloc->common.version = 0;
+	module->alloc->common.module = (hw_module_t *)mod;
+	module->alloc->common.close = gralloc0_close;
+
+	*dev = &module->alloc->common;
+	return CROS_GRALLOC_ERROR_NONE;
+}
+
+static int gralloc0_register_buffer(struct gralloc_module_t const *module, buffer_handle_t handle)
+{
+	auto mod = (struct gralloc0_module *)module;
+
+	if (!mod->driver) {
+		mod->driver = std::make_unique<cros_gralloc_driver>();
+		if (mod->driver->init()) {
+			cros_gralloc_error("Failed to initialize driver.");
+			return CROS_GRALLOC_ERROR_NO_RESOURCES;
+		}
+	}
+
+	return mod->driver->retain(handle);
+}
+
+static int gralloc0_unregister_buffer(struct gralloc_module_t const *module, buffer_handle_t handle)
+{
+	auto mod = (struct gralloc0_module *)module;
+	return mod->driver->release(handle);
+}
+
+static int gralloc0_lock(struct gralloc_module_t const *module, buffer_handle_t handle, int usage,
+			 int l, int t, int w, int h, void **vaddr)
+{
+	int32_t ret, fence;
+	uint64_t flags;
+	uint8_t *addr[DRV_MAX_PLANES];
+	auto mod = (struct gralloc0_module *)module;
+
+	auto hnd = cros_gralloc_convert_handle(handle);
+	if (!hnd) {
+		cros_gralloc_error("Invalid handle.");
+		return CROS_GRALLOC_ERROR_BAD_HANDLE;
+	}
+
+	if ((hnd->droid_format == HAL_PIXEL_FORMAT_YCbCr_420_888)) {
+		cros_gralloc_error("HAL_PIXEL_FORMAT_YCbCr_*_888 format not compatible.");
+		return CROS_GRALLOC_ERROR_BAD_HANDLE;
+	}
+
+	fence = -1;
+	flags = gralloc0_convert_flags(usage);
+	ret = mod->driver->lock(handle, fence, flags, addr);
+	*vaddr = addr[0];
+	return ret;
+}
+
+static int gralloc0_unlock(struct gralloc_module_t const *module, buffer_handle_t handle)
+{
+	auto mod = (struct gralloc0_module *)module;
+	return mod->driver->unlock(handle);
+}
+
+static int gralloc0_perform(struct gralloc_module_t const *module, int op, ...)
+{
+	va_list args;
+	int32_t *out_format, ret;
+	uint64_t *out_store;
+	buffer_handle_t handle;
+	uint32_t *out_width, *out_height, *out_stride;
+	auto mod = (struct gralloc0_module *)module;
+
+	switch (op) {
+	case GRALLOC_DRM_GET_STRIDE:
+	case GRALLOC_DRM_GET_FORMAT:
+	case GRALLOC_DRM_GET_DIMENSIONS:
+	case GRALLOC_DRM_GET_BACKING_STORE:
+		break;
+	default:
+		return CROS_GRALLOC_ERROR_UNSUPPORTED;
+	}
+
+	va_start(args, op);
+
+	ret = CROS_GRALLOC_ERROR_NONE;
+	handle = va_arg(args, buffer_handle_t);
+	auto hnd = cros_gralloc_convert_handle(handle);
+	if (!hnd) {
+		cros_gralloc_error("Invalid handle.");
+		return CROS_GRALLOC_ERROR_BAD_HANDLE;
+	}
+
+	switch (op) {
+	case GRALLOC_DRM_GET_STRIDE:
+		out_stride = va_arg(args, uint32_t *);
+		*out_stride = hnd->pixel_stride;
+		break;
+	case GRALLOC_DRM_GET_FORMAT:
+		out_format = va_arg(args, int32_t *);
+		*out_format = hnd->droid_format;
+		break;
+	case GRALLOC_DRM_GET_DIMENSIONS:
+		out_width = va_arg(args, uint32_t *);
+		out_height = va_arg(args, uint32_t *);
+		*out_width = hnd->width;
+		*out_height = hnd->height;
+		break;
+	case GRALLOC_DRM_GET_BACKING_STORE:
+		out_store = va_arg(args, uint64_t *);
+		ret = mod->driver->get_backing_store(handle, out_store);
+		break;
+	default:
+		ret = CROS_GRALLOC_ERROR_UNSUPPORTED;
+	}
+
+	va_end(args);
+
+	return ret;
+}
+
+static int gralloc0_lock_ycbcr(struct gralloc_module_t const *module, buffer_handle_t handle,
+			       int usage, int l, int t, int w, int h, struct android_ycbcr *ycbcr)
+{
+	uint64_t flags;
+	int32_t fence, ret;
+	uint8_t *addr[DRV_MAX_PLANES] = { nullptr, nullptr, nullptr, nullptr };
+	auto mod = (struct gralloc0_module *)module;
+
+	auto hnd = cros_gralloc_convert_handle(handle);
+	if (!hnd) {
+		cros_gralloc_error("Invalid handle.");
+		return CROS_GRALLOC_ERROR_BAD_HANDLE;
+	}
+
+	if ((hnd->droid_format != HAL_PIXEL_FORMAT_YCbCr_420_888) &&
+	    (hnd->droid_format != HAL_PIXEL_FORMAT_YV12)) {
+		cros_gralloc_error("Non-YUV format not compatible.");
+		return CROS_GRALLOC_ERROR_BAD_HANDLE;
+	}
+
+	fence = -1;
+	flags = gralloc0_convert_flags(usage);
+	ret = mod->driver->lock(handle, fence, flags, addr);
+
+	switch (hnd->format) {
+	case DRM_FORMAT_NV12:
+		ycbcr->y = addr[0];
+		ycbcr->cb = addr[1];
+		ycbcr->cr = addr[1] + 1;
+		ycbcr->ystride = hnd->strides[0];
+		ycbcr->cstride = hnd->strides[1];
+		ycbcr->chroma_step = 2;
+		break;
+	case DRM_FORMAT_YVU420:
+	case DRM_FORMAT_YVU420_ANDROID:
+		ycbcr->y = addr[0];
+		ycbcr->cb = addr[2];
+		ycbcr->cr = addr[1];
+		ycbcr->ystride = hnd->strides[0];
+		ycbcr->cstride = hnd->strides[1];
+		ycbcr->chroma_step = 1;
+		break;
+	default:
+		return CROS_GRALLOC_ERROR_UNSUPPORTED;
+	}
+
+	return ret;
+}
+
+static struct hw_module_methods_t gralloc0_module_methods = {.open = gralloc0_open };
+
+struct gralloc0_module HAL_MODULE_INFO_SYM = {
+	.base =
+	    {
+		.common =
+		    {
+			.tag = HARDWARE_MODULE_TAG,
+			.module_api_version = GRALLOC_MODULE_API_VERSION_0_2,
+			.hal_api_version = 0,
+			.id = GRALLOC_HARDWARE_MODULE_ID,
+			.name = "CrOS Gralloc",
+			.author = "Chrome OS",
+			.methods = &gralloc0_module_methods,
+		    },
+
+		.registerBuffer = gralloc0_register_buffer,
+		.unregisterBuffer = gralloc0_unregister_buffer,
+		.lock = gralloc0_lock,
+		.unlock = gralloc0_unlock,
+		.perform = gralloc0_perform,
+		.lock_ycbcr = gralloc0_lock_ycbcr,
+	    },
+
+	.alloc = nullptr,
+	.driver = nullptr,
+};