minigbm: virtio_gpu: select dumb/virgl at runtime.

For using same image on legacy-qemu and virgl enabled qemu. We need
to handle dumb and virgl code path at run time. Just merge them to
one driver.

BUG=b:77302150
TEST=manual - run novato image under qemu with gl=on/off.

Change-Id: Ia12140fba16a350fe13f4258d25333ecfe8352b3
Reviewed-on: https://chromium-review.googlesource.com/998631
Commit-Ready: Lepton Wu <lepton@chromium.org>
Tested-by: Lepton Wu <lepton@chromium.org>
Reviewed-by: Lepton Wu <lepton@chromium.org>
Reviewed-by: Gurchetan Singh <gurchetansingh@chromium.org>
diff --git a/Android.mk b/Android.mk
index 0abeaf4..e75766f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -26,8 +26,7 @@
 	udl.c \
 	vc4.c \
 	vgem.c \
-	virtio_dumb.c \
-	virtio_virgl.c
+	virtio_gpu.c
 
 MINIGBM_CPPFLAGS := -std=c++14 -D_GNU_SOURCE=1 -D_FILE_OFFSET_BITS=64
 MINIGBM_CFLAGS := -Wall -Wsign-compare -Wpointer-arith \
@@ -40,11 +39,6 @@
 LOCAL_SHARED_LIBRARIES += libdrm_intel
 endif
 
-ifneq ($(filter virgl, $(BOARD_GPU_DRIVERS)),)
-MINIGBM_CPPFLAGS += -DDRV_VIRGL
-MINIGBM_CFLAGS += -DDRV_VIRGL
-endif
-
 ifneq ($(filter meson, $(BOARD_GPU_DRIVERS)),)
 MINIGBM_CPPFLAGS += -DDRV_MESON
 MINIGBM_CFLAGS += -DDRV_MESON
diff --git a/virtio_dumb.c b/virtio_dumb.c
deleted file mode 100644
index b6dc3cb..0000000
--- a/virtio_dumb.c
+++ /dev/null
@@ -1,71 +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 DRV_VIRGL
-
-#include "drv_priv.h"
-#include "helpers.h"
-#include "util.h"
-
-#define MESA_LLVMPIPE_TILE_ORDER 6
-#define MESA_LLVMPIPE_TILE_SIZE (1 << MESA_LLVMPIPE_TILE_ORDER)
-
-static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888,
-						  DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888,
-						  DRM_FORMAT_XRGB8888 };
-
-static const uint32_t texture_source_formats[] = { DRM_FORMAT_R8, DRM_FORMAT_YVU420,
-						   DRM_FORMAT_YVU420_ANDROID };
-
-static int virtio_gpu_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 virtio_gpu_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
-				uint64_t use_flags)
-{
-	width = ALIGN(width, MESA_LLVMPIPE_TILE_SIZE);
-	height = ALIGN(height, MESA_LLVMPIPE_TILE_SIZE);
-
-	/* HAL_PIXEL_FORMAT_YV12 requires that the buffer's height not be aligned. */
-	if (bo->format == DRM_FORMAT_YVU420_ANDROID)
-		height = bo->height;
-
-	return drv_dumb_bo_create(bo, width, height, format, use_flags);
-}
-
-static uint32_t virtio_gpu_resolve_format(uint32_t format, uint64_t use_flags)
-{
-	switch (format) {
-	case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
-		/*HACK: See b/28671744 */
-		return DRM_FORMAT_XBGR8888;
-	case DRM_FORMAT_FLEX_YCbCr_420_888:
-		return DRM_FORMAT_YVU420;
-	default:
-		return format;
-	}
-}
-
-const struct backend backend_virtio_gpu = {
-	.name = "virtio_gpu",
-	.init = virtio_gpu_init,
-	.bo_create = virtio_gpu_bo_create,
-	.bo_destroy = drv_dumb_bo_destroy,
-	.bo_import = drv_prime_bo_import,
-	.bo_map = drv_dumb_bo_map,
-	.bo_unmap = drv_bo_munmap,
-	.resolve_format = virtio_gpu_resolve_format,
-};
-
-#endif
diff --git a/virtio_virgl.c b/virtio_gpu.c
similarity index 65%
rename from virtio_virgl.c
rename to virtio_gpu.c
index 2b445a6..5200b3d 100644
--- a/virtio_virgl.c
+++ b/virtio_gpu.c
@@ -4,8 +4,6 @@
  * found in the LICENSE file.
  */
 
-#ifdef DRV_VIRGL
-
 #include <errno.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -24,12 +22,22 @@
 #endif
 #define PIPE_TEXTURE_2D 2
 
+#define MESA_LLVMPIPE_TILE_ORDER 6
+#define MESA_LLVMPIPE_TILE_SIZE (1 << MESA_LLVMPIPE_TILE_ORDER)
+
 static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888,
 						  DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888,
 						  DRM_FORMAT_XRGB8888 };
 
+static const uint32_t dumb_texture_source_formats[] = { DRM_FORMAT_R8, DRM_FORMAT_YVU420,
+							DRM_FORMAT_YVU420_ANDROID };
+
 static const uint32_t texture_source_formats[] = { DRM_FORMAT_R8, DRM_FORMAT_RG88 };
 
+struct virtio_gpu_priv {
+	int has_3d;
+};
+
 static uint32_t translate_format(uint32_t drm_fourcc, uint32_t plane)
 {
 	switch (drm_fourcc) {
@@ -52,19 +60,21 @@
 	}
 }
 
-static int virtio_gpu_init(struct driver *drv)
+static int virtio_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+				 uint64_t use_flags)
 {
-	drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
-			     &LINEAR_METADATA, BO_USE_RENDER_MASK);
+	width = ALIGN(width, MESA_LLVMPIPE_TILE_SIZE);
+	height = ALIGN(height, MESA_LLVMPIPE_TILE_SIZE);
 
-	drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats),
-			     &LINEAR_METADATA, BO_USE_TEXTURE_MASK);
+	/* HAL_PIXEL_FORMAT_YV12 requires that the buffer's height not be aligned. */
+	if (bo->format == DRM_FORMAT_YVU420_ANDROID)
+		height = bo->height;
 
-	return drv_modify_linear_combinations(drv);
+	return drv_dumb_bo_create(bo, width, height, format, use_flags);
 }
 
-static int virtio_gpu_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
-				uint64_t use_flags)
+static int virtio_virgl_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+				  uint64_t use_flags)
 {
 	int ret;
 	ssize_t plane;
@@ -127,7 +137,7 @@
 	return ret;
 }
 
-static void *virgl_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
+static void *virtio_virgl_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
 {
 	int ret;
 	struct drm_virtgpu_map gem_map;
@@ -146,10 +156,82 @@
 		    gem_map.offset);
 }
 
+static int virtio_gpu_init(struct driver *drv)
+{
+	int ret;
+	struct virtio_gpu_priv *priv;
+	struct drm_virtgpu_getparam args;
+
+	priv = calloc(1, sizeof(*priv));
+	drv->priv = priv;
+
+	memset(&args, 0, sizeof(args));
+	args.param = VIRTGPU_PARAM_3D_FEATURES;
+	args.value = (uint64_t)(uintptr_t)&priv->has_3d;
+	ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GETPARAM, &args);
+	if (ret) {
+		drv_log("virtio 3D acceleration is not available\n");
+		/* Be paranoid */
+		priv->has_3d = 0;
+	}
+
+	drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+			     &LINEAR_METADATA, BO_USE_RENDER_MASK);
+
+	if (priv->has_3d)
+		drv_add_combinations(drv, texture_source_formats,
+				     ARRAY_SIZE(texture_source_formats), &LINEAR_METADATA,
+				     BO_USE_TEXTURE_MASK);
+	else
+		drv_add_combinations(drv, dumb_texture_source_formats,
+				     ARRAY_SIZE(dumb_texture_source_formats), &LINEAR_METADATA,
+				     BO_USE_TEXTURE_MASK);
+
+	return drv_modify_linear_combinations(drv);
+}
+
+static void virtio_gpu_close(struct driver *drv)
+{
+	free(drv->priv);
+	drv->priv = NULL;
+}
+
+static int virtio_gpu_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+				uint64_t use_flags)
+{
+	struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)bo->drv->priv;
+	if (priv->has_3d)
+		return virtio_virgl_bo_create(bo, width, height, format, use_flags);
+	else
+		return virtio_dumb_bo_create(bo, width, height, format, use_flags);
+}
+
+static int virtio_gpu_bo_destroy(struct bo *bo)
+{
+	struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)bo->drv->priv;
+	if (priv->has_3d)
+		return drv_gem_bo_destroy(bo);
+	else
+		return drv_dumb_bo_destroy(bo);
+}
+
+static void *virtio_gpu_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
+{
+	struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)bo->drv->priv;
+	if (priv->has_3d)
+		return virtio_virgl_bo_map(bo, vma, plane, map_flags);
+	else
+		return drv_dumb_bo_map(bo, vma, plane, map_flags);
+}
+
 static int virtio_gpu_bo_invalidate(struct bo *bo, struct mapping *mapping)
 {
 	int ret;
 	struct drm_virtgpu_3d_transfer_from_host xfer;
+	struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)bo->drv->priv;
+
+	if (!priv->has_3d)
+		return 0;
 
 	memset(&xfer, 0, sizeof(xfer));
 	xfer.bo_handle = mapping->vma->handle;
@@ -172,6 +254,10 @@
 {
 	int ret;
 	struct drm_virtgpu_3d_transfer_to_host xfer;
+	struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)bo->drv->priv;
+
+	if (!priv->has_3d)
+		return 0;
 
 	if (!(mapping->vma->map_flags & BO_MAP_WRITE))
 		return 0;
@@ -199,22 +285,23 @@
 	case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
 		/*HACK: See b/28671744 */
 		return DRM_FORMAT_XBGR8888;
+	case DRM_FORMAT_FLEX_YCbCr_420_888:
+		return DRM_FORMAT_YVU420;
 	default:
 		return format;
 	}
 }
 
-struct backend backend_virtio_gpu = {
+const struct backend backend_virtio_gpu = {
 	.name = "virtio_gpu",
 	.init = virtio_gpu_init,
+	.close = virtio_gpu_close,
 	.bo_create = virtio_gpu_bo_create,
-	.bo_destroy = drv_gem_bo_destroy,
+	.bo_destroy = virtio_gpu_bo_destroy,
 	.bo_import = drv_prime_bo_import,
-	.bo_map = virgl_bo_map,
+	.bo_map = virtio_gpu_bo_map,
 	.bo_unmap = drv_bo_munmap,
 	.bo_invalidate = virtio_gpu_bo_invalidate,
 	.bo_flush = virtio_gpu_bo_flush,
 	.resolve_format = virtio_gpu_resolve_format,
 };
-
-#endif