summaryrefslogtreecommitdiff
path: root/chromium/third_party/minigbm
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-01-31 16:33:43 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-02-06 16:33:22 +0000
commitda51f56cc21233c2d30f0fe0d171727c3102b2e0 (patch)
tree4e579ab70ce4b19bee7984237f3ce05a96d59d83 /chromium/third_party/minigbm
parentc8c2d1901aec01e934adf561a9fdf0cc776cdef8 (diff)
downloadqtwebengine-chromium-da51f56cc21233c2d30f0fe0d171727c3102b2e0.tar.gz
BASELINE: Update Chromium to 65.0.3525.40
Also imports missing submodules Change-Id: I36901b7c6a325cda3d2c10cedb2186c25af3b79b Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/third_party/minigbm')
-rw-r--r--chromium/third_party/minigbm/src/.clang-format15
-rw-r--r--chromium/third_party/minigbm/src/Android.gralloc.mk11
-rw-r--r--chromium/third_party/minigbm/src/Android.mk59
-rw-r--r--chromium/third_party/minigbm/src/LICENSE27
-rw-r--r--chromium/third_party/minigbm/src/Makefile54
-rw-r--r--chromium/third_party/minigbm/src/PRESUBMIT.cfg12
-rw-r--r--chromium/third_party/minigbm/src/amdgpu.c442
-rw-r--r--chromium/third_party/minigbm/src/cirrus.c32
-rw-r--r--chromium/third_party/minigbm/src/common.mk931
-rw-r--r--chromium/third_party/minigbm/src/cros_gralloc/Makefile46
-rw-r--r--chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_buffer.cc98
-rw-r--r--chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_buffer.h44
-rw-r--r--chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_driver.cc316
-rw-r--r--chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_driver.h47
-rw-r--r--chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_handle.h39
-rw-r--r--chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_helpers.cc95
-rw-r--r--chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_helpers.h35
-rw-r--r--chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_types.h20
-rw-r--r--chromium/third_party/minigbm/src/cros_gralloc/gralloc0/gralloc0.cc398
-rw-r--r--chromium/third_party/minigbm/src/drv.c608
-rw-r--r--chromium/third_party/minigbm/src/drv.h154
-rw-r--r--chromium/third_party/minigbm/src/drv_priv.h95
-rw-r--r--chromium/third_party/minigbm/src/evdi.c31
-rw-r--r--chromium/third_party/minigbm/src/exynos.c117
-rw-r--r--chromium/third_party/minigbm/src/gbm.c338
-rw-r--r--chromium/third_party/minigbm/src/gbm.h425
-rw-r--r--chromium/third_party/minigbm/src/gbm.pc10
-rw-r--r--chromium/third_party/minigbm/src/gbm_helpers.c35
-rw-r--r--chromium/third_party/minigbm/src/gbm_helpers.h12
-rw-r--r--chromium/third_party/minigbm/src/gbm_priv.h32
-rw-r--r--chromium/third_party/minigbm/src/gma500.c31
-rw-r--r--chromium/third_party/minigbm/src/helpers.c549
-rw-r--r--chromium/third_party/minigbm/src/helpers.h32
-rw-r--r--chromium/third_party/minigbm/src/i915.c513
-rw-r--r--chromium/third_party/minigbm/src/marvell.c36
-rw-r--r--chromium/third_party/minigbm/src/mediatek.c150
-rw-r--r--chromium/third_party/minigbm/src/nouveau.c31
-rwxr-xr-xchromium/third_party/minigbm/src/presubmit.sh8
-rw-r--r--chromium/third_party/minigbm/src/radeon.c31
-rw-r--r--chromium/third_party/minigbm/src/rockchip.c308
-rw-r--r--chromium/third_party/minigbm/src/tegra.c359
-rw-r--r--chromium/third_party/minigbm/src/udl.c31
-rw-r--r--chromium/third_party/minigbm/src/util.h16
-rw-r--r--chromium/third_party/minigbm/src/vc4.c92
-rw-r--r--chromium/third_party/minigbm/src/vgem.c71
-rw-r--r--chromium/third_party/minigbm/src/virtio_gpu.c71
46 files changed, 6907 insertions, 0 deletions
diff --git a/chromium/third_party/minigbm/src/.clang-format b/chromium/third_party/minigbm/src/.clang-format
new file mode 100644
index 00000000000..6628ecda0a1
--- /dev/null
+++ b/chromium/third_party/minigbm/src/.clang-format
@@ -0,0 +1,15 @@
+# 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.
+
+BasedOnStyle: LLVM
+AllowShortFunctionsOnASingleLine: None
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+BreakBeforeBraces: Linux
+ColumnLimit: 100
+IndentWidth: 8
+TabWidth: 8
+UseTab: Always
+Cpp11BracedListStyle: false
+IndentCaseLabels: false
diff --git a/chromium/third_party/minigbm/src/Android.gralloc.mk b/chromium/third_party/minigbm/src/Android.gralloc.mk
new file mode 100644
index 00000000000..ff269c00aed
--- /dev/null
+++ b/chromium/third_party/minigbm/src/Android.gralloc.mk
@@ -0,0 +1,11 @@
+# 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/chromium/third_party/minigbm/src/Android.mk b/chromium/third_party/minigbm/src/Android.mk
new file mode 100644
index 00000000000..c4798adb197
--- /dev/null
+++ b/chromium/third_party/minigbm/src/Android.mk
@@ -0,0 +1,59 @@
+# 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.
+
+ifeq ($(strip $(BOARD_USES_MINIGBM)), true)
+
+MINIGBM_GRALLOC_MK := $(call my-dir)/Android.gralloc.mk
+LOCAL_PATH := $(call my-dir)
+intel_drivers := i915 i965
+include $(CLEAR_VARS)
+
+SUBDIRS := cros_gralloc
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libdrm
+
+LOCAL_SRC_FILES := \
+ amdgpu.c \
+ cirrus.c \
+ drv.c \
+ evdi.c \
+ exynos.c \
+ gma500.c \
+ helpers.c \
+ i915.c \
+ marvell.c \
+ mediatek.c \
+ nouveau.c \
+ rockchip.c \
+ tegra.c \
+ udl.c \
+ vc4.c \
+ vgem.c \
+ virtio_gpu.c
+
+include $(MINIGBM_GRALLOC_MK)
+
+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
+
+ifneq ($(filter $(intel_drivers), $(BOARD_GPU_DRIVERS)),)
+LOCAL_CPPFLAGS += -DDRV_I915
+LOCAL_CFLAGS += -DDRV_I915
+LOCAL_SHARED_LIBRARIES += libdrm_intel
+endif
+
+LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM)
+LOCAL_MODULE_TAGS := optional
+# The preferred path for vendor HALs is /vendor/lib/hw
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_MODULE_SUFFIX := $(TARGET_SHLIB_SUFFIX)
+include $(BUILD_SHARED_LIBRARY)
+
+#endif
diff --git a/chromium/third_party/minigbm/src/LICENSE b/chromium/third_party/minigbm/src/LICENSE
new file mode 100644
index 00000000000..3bd5095873d
--- /dev/null
+++ b/chromium/third_party/minigbm/src/LICENSE
@@ -0,0 +1,27 @@
+// Copyright (c) 2017 The Chromium OS Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/chromium/third_party/minigbm/src/Makefile b/chromium/third_party/minigbm/src/Makefile
new file mode 100644
index 00000000000..482e074a232
--- /dev/null
+++ b/chromium/third_party/minigbm/src/Makefile
@@ -0,0 +1,54 @@
+# Copyright 2014 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+include common.mk
+
+PC_DEPS = libdrm
+PC_CFLAGS := $(shell $(PKG_CONFIG) --cflags $(PC_DEPS))
+PC_LIBS := $(shell $(PKG_CONFIG) --libs $(PC_DEPS))
+
+CPPFLAGS += -D_GNU_SOURCE=1
+CFLAGS += -std=c99 -Wall -Wsign-compare -Wpointer-arith -Wcast-qual \
+ -Wcast-align -D_GNU_SOURCE=1 -D_FILE_OFFSET_BITS=64
+
+ifdef DRV_AMDGPU
+ CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_amdgpu)
+ LDLIBS += -lamdgpuaddr
+endif
+ifdef DRV_EXYNOS
+ CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_exynos)
+endif
+ifdef DRV_I915
+ CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_intel)
+endif
+ifdef DRV_RADEON
+ CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_radeon)
+endif
+ifdef DRV_ROCKCHIP
+ CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_rockchip)
+endif
+
+CPPFLAGS += $(PC_CFLAGS)
+LDLIBS += $(PC_LIBS)
+
+LIBDIR ?= /usr/lib/
+
+GBM_VERSION_MAJOR := 1
+MINIGBM_VERSION := $(GBM_VERSION_MAJOR).0.0
+MINIGBM_FILENAME := libminigbm.so.$(MINIGBM_VERSION)
+
+CC_LIBRARY($(MINIGBM_FILENAME)): LDFLAGS += -Wl,-soname,libgbm.so.$(GBM_VERSION_MAJOR)
+CC_LIBRARY($(MINIGBM_FILENAME)): $(C_OBJECTS)
+
+all: CC_LIBRARY($(MINIGBM_FILENAME))
+
+clean: CLEAN($(MINIGBM_FILENAME))
+
+install: all
+ mkdir -p $(DESTDIR)/$(LIBDIR)
+ install -D -m 755 $(OUT)/$(MINIGBM_FILENAME) $(DESTDIR)/$(LIBDIR)
+ ln -sf $(MINIGBM_FILENAME) $(DESTDIR)/$(LIBDIR)/libgbm.so
+ ln -sf $(MINIGBM_FILENAME) $(DESTDIR)/$(LIBDIR)/libgbm.so.$(GBM_VERSION_MAJOR)
+ install -D -m 0644 $(SRC)/gbm.pc $(DESTDIR)$(LIBDIR)/pkgconfig/gbm.pc
+ install -D -m 0644 $(SRC)/gbm.h $(DESTDIR)/usr/include/gbm.h
diff --git a/chromium/third_party/minigbm/src/PRESUBMIT.cfg b/chromium/third_party/minigbm/src/PRESUBMIT.cfg
new file mode 100644
index 00000000000..5dfbb4b7dfd
--- /dev/null
+++ b/chromium/third_party/minigbm/src/PRESUBMIT.cfg
@@ -0,0 +1,12 @@
+# 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.
+[Hook Overrides]
+stray_whitespace_check: false
+long_line_check: false
+cros_license_check: false
+tab_check: false
+bug_field_check: false
+test_field_check: false
+[Hook Scripts]
+hook0 = ./presubmit.sh
diff --git a/chromium/third_party/minigbm/src/amdgpu.c b/chromium/third_party/minigbm/src/amdgpu.c
new file mode 100644
index 00000000000..ff1336dbc75
--- /dev/null
+++ b/chromium/third_party/minigbm/src/amdgpu.c
@@ -0,0 +1,442 @@
+/*
+ * 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.
+ */
+#ifdef DRV_AMDGPU
+#include <amdgpu.h>
+#include <amdgpu_drm.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <xf86drm.h>
+
+#include "addrinterface.h"
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+#ifndef CIASICIDGFXENGINE_SOUTHERNISLAND
+#define CIASICIDGFXENGINE_SOUTHERNISLAND 0x0000000A
+#endif
+
+// clang-format off
+#define mmCC_RB_BACKEND_DISABLE 0x263d
+#define mmGB_TILE_MODE0 0x2644
+#define mmGB_MACROTILE_MODE0 0x2664
+#define mmGB_ADDR_CONFIG 0x263e
+#define mmMC_ARB_RAMCFG 0x9d8
+
+enum {
+ FAMILY_UNKNOWN,
+ FAMILY_SI,
+ FAMILY_CI,
+ FAMILY_KV,
+ FAMILY_VI,
+ FAMILY_CZ,
+ FAMILY_PI,
+ FAMILY_LAST,
+};
+// clang-format on
+
+const static uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XBGR8888,
+ DRM_FORMAT_XRGB8888 };
+
+const static uint32_t texture_source_formats[] = { DRM_FORMAT_NV21, DRM_FORMAT_NV12 };
+
+static int amdgpu_set_metadata(int fd, uint32_t handle, struct amdgpu_bo_metadata *info)
+{
+ struct drm_amdgpu_gem_metadata args = { 0 };
+
+ if (!info)
+ return -EINVAL;
+
+ args.handle = handle;
+ args.op = AMDGPU_GEM_METADATA_OP_SET_METADATA;
+ args.data.flags = info->flags;
+ args.data.tiling_info = info->tiling_info;
+
+ if (info->size_metadata > sizeof(args.data.data))
+ return -EINVAL;
+
+ if (info->size_metadata) {
+ args.data.data_size_bytes = info->size_metadata;
+ memcpy(args.data.data, info->umd_metadata, info->size_metadata);
+ }
+
+ return drmCommandWriteRead(fd, DRM_AMDGPU_GEM_METADATA, &args, sizeof(args));
+}
+
+static int amdgpu_read_mm_regs(int fd, unsigned dword_offset, unsigned count, uint32_t instance,
+ uint32_t flags, uint32_t *values)
+{
+ struct drm_amdgpu_info request;
+
+ memset(&request, 0, sizeof(request));
+ request.return_pointer = (uintptr_t)values;
+ request.return_size = count * sizeof(uint32_t);
+ request.query = AMDGPU_INFO_READ_MMR_REG;
+ request.read_mmr_reg.dword_offset = dword_offset;
+ request.read_mmr_reg.count = count;
+ request.read_mmr_reg.instance = instance;
+ request.read_mmr_reg.flags = flags;
+
+ return drmCommandWrite(fd, DRM_AMDGPU_INFO, &request, sizeof(struct drm_amdgpu_info));
+}
+
+static int amdgpu_query_gpu(int fd, struct amdgpu_gpu_info *gpu_info)
+{
+ int ret;
+ uint32_t instance;
+
+ if (!gpu_info)
+ return -EINVAL;
+
+ instance = AMDGPU_INFO_MMR_SH_INDEX_MASK << AMDGPU_INFO_MMR_SH_INDEX_SHIFT;
+
+ ret = amdgpu_read_mm_regs(fd, mmCC_RB_BACKEND_DISABLE, 1, instance, 0,
+ &gpu_info->backend_disable[0]);
+ if (ret)
+ return ret;
+ /* extract bitfield CC_RB_BACKEND_DISABLE.BACKEND_DISABLE */
+ gpu_info->backend_disable[0] = (gpu_info->backend_disable[0] >> 16) & 0xff;
+
+ ret = amdgpu_read_mm_regs(fd, mmGB_TILE_MODE0, 32, 0xffffffff, 0, gpu_info->gb_tile_mode);
+ if (ret)
+ return ret;
+
+ ret = amdgpu_read_mm_regs(fd, mmGB_MACROTILE_MODE0, 16, 0xffffffff, 0,
+ gpu_info->gb_macro_tile_mode);
+ if (ret)
+ return ret;
+
+ ret = amdgpu_read_mm_regs(fd, mmGB_ADDR_CONFIG, 1, 0xffffffff, 0, &gpu_info->gb_addr_cfg);
+ if (ret)
+ return ret;
+
+ ret = amdgpu_read_mm_regs(fd, mmMC_ARB_RAMCFG, 1, 0xffffffff, 0, &gpu_info->mc_arb_ramcfg);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static void *ADDR_API alloc_sys_mem(const ADDR_ALLOCSYSMEM_INPUT *in)
+{
+ return malloc(in->sizeInBytes);
+}
+
+static ADDR_E_RETURNCODE ADDR_API free_sys_mem(const ADDR_FREESYSMEM_INPUT *in)
+{
+ free(in->pVirtAddr);
+ return ADDR_OK;
+}
+
+static int amdgpu_addrlib_compute(void *addrlib, uint32_t width, uint32_t height, uint32_t format,
+ uint32_t usage, uint32_t *tiling_flags,
+ ADDR_COMPUTE_SURFACE_INFO_OUTPUT *addr_out)
+{
+ ADDR_COMPUTE_SURFACE_INFO_INPUT addr_surf_info_in = { 0 };
+ ADDR_TILEINFO addr_tile_info = { 0 };
+ ADDR_TILEINFO addr_tile_info_out = { 0 };
+ uint32_t bits_per_pixel;
+
+ addr_surf_info_in.size = sizeof(ADDR_COMPUTE_SURFACE_INFO_INPUT);
+
+ /* Set the requested tiling mode. */
+ addr_surf_info_in.tileMode = ADDR_TM_2D_TILED_THIN1;
+ if (usage & (BO_USE_CURSOR | BO_USE_LINEAR | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN))
+ addr_surf_info_in.tileMode = ADDR_TM_LINEAR_ALIGNED;
+ else if (width <= 16 || height <= 16)
+ addr_surf_info_in.tileMode = ADDR_TM_1D_TILED_THIN1;
+
+ bits_per_pixel = drv_stride_from_format(format, 1, 0) * 8;
+ /* Bits per pixel should be calculated from format*/
+ addr_surf_info_in.bpp = bits_per_pixel;
+ addr_surf_info_in.numSamples = 1;
+ addr_surf_info_in.width = width;
+ addr_surf_info_in.height = height;
+ addr_surf_info_in.numSlices = 1;
+ addr_surf_info_in.pTileInfo = &addr_tile_info;
+ addr_surf_info_in.tileIndex = -1;
+
+ /* This disables incorrect calculations (hacks) in addrlib. */
+ addr_surf_info_in.flags.noStencil = 1;
+
+ /* Set the micro tile type. */
+ if (usage & BO_USE_SCANOUT)
+ addr_surf_info_in.tileType = ADDR_DISPLAYABLE;
+ else
+ addr_surf_info_in.tileType = ADDR_NON_DISPLAYABLE;
+
+ addr_out->size = sizeof(ADDR_COMPUTE_SURFACE_INFO_OUTPUT);
+ addr_out->pTileInfo = &addr_tile_info_out;
+
+ if (AddrComputeSurfaceInfo(addrlib, &addr_surf_info_in, addr_out) != ADDR_OK)
+ return -EINVAL;
+
+ ADDR_CONVERT_TILEINFOTOHW_INPUT s_in = { 0 };
+ ADDR_CONVERT_TILEINFOTOHW_OUTPUT s_out = { 0 };
+ ADDR_TILEINFO s_tile_hw_info_out = { 0 };
+
+ s_in.size = sizeof(ADDR_CONVERT_TILEINFOTOHW_INPUT);
+ /* Convert from real value to HW value */
+ s_in.reverse = 0;
+ s_in.pTileInfo = &addr_tile_info_out;
+ s_in.tileIndex = -1;
+
+ s_out.size = sizeof(ADDR_CONVERT_TILEINFOTOHW_OUTPUT);
+ s_out.pTileInfo = &s_tile_hw_info_out;
+
+ if (AddrConvertTileInfoToHW(addrlib, &s_in, &s_out) != ADDR_OK)
+ return -EINVAL;
+
+ if (addr_out->tileMode >= ADDR_TM_2D_TILED_THIN1)
+ /* 2D_TILED_THIN1 */
+ *tiling_flags |= AMDGPU_TILING_SET(ARRAY_MODE, 4);
+ else if (addr_out->tileMode >= ADDR_TM_1D_TILED_THIN1)
+ /* 1D_TILED_THIN1 */
+ *tiling_flags |= AMDGPU_TILING_SET(ARRAY_MODE, 2);
+ else
+ /* LINEAR_ALIGNED */
+ *tiling_flags |= AMDGPU_TILING_SET(ARRAY_MODE, 1);
+
+ *tiling_flags |= AMDGPU_TILING_SET(BANK_WIDTH, drv_log_base2(addr_tile_info_out.bankWidth));
+ *tiling_flags |=
+ AMDGPU_TILING_SET(BANK_HEIGHT, drv_log_base2(addr_tile_info_out.bankHeight));
+ *tiling_flags |= AMDGPU_TILING_SET(TILE_SPLIT, s_tile_hw_info_out.tileSplitBytes);
+ *tiling_flags |= AMDGPU_TILING_SET(MACRO_TILE_ASPECT,
+ drv_log_base2(addr_tile_info_out.macroAspectRatio));
+ *tiling_flags |= AMDGPU_TILING_SET(PIPE_CONFIG, s_tile_hw_info_out.pipeConfig);
+ *tiling_flags |= AMDGPU_TILING_SET(NUM_BANKS, s_tile_hw_info_out.banks);
+
+ return 0;
+}
+
+static void *amdgpu_addrlib_init(int fd)
+{
+ int ret;
+ ADDR_CREATE_INPUT addr_create_input = { 0 };
+ ADDR_CREATE_OUTPUT addr_create_output = { 0 };
+ ADDR_REGISTER_VALUE reg_value = { 0 };
+ ADDR_CREATE_FLAGS create_flags = { { 0 } };
+ ADDR_E_RETURNCODE addr_ret;
+
+ addr_create_input.size = sizeof(ADDR_CREATE_INPUT);
+ addr_create_output.size = sizeof(ADDR_CREATE_OUTPUT);
+
+ struct amdgpu_gpu_info gpu_info = { 0 };
+
+ ret = amdgpu_query_gpu(fd, &gpu_info);
+
+ if (ret) {
+ fprintf(stderr, "[%s]failed with error =%d\n", __func__, ret);
+ return NULL;
+ }
+
+ reg_value.noOfBanks = gpu_info.mc_arb_ramcfg & 0x3;
+ reg_value.gbAddrConfig = gpu_info.gb_addr_cfg;
+ reg_value.noOfRanks = (gpu_info.mc_arb_ramcfg & 0x4) >> 2;
+
+ reg_value.backendDisables = gpu_info.backend_disable[0];
+ reg_value.pTileConfig = gpu_info.gb_tile_mode;
+ reg_value.noOfEntries = sizeof(gpu_info.gb_tile_mode) / sizeof(gpu_info.gb_tile_mode[0]);
+ reg_value.pMacroTileConfig = gpu_info.gb_macro_tile_mode;
+ reg_value.noOfMacroEntries =
+ sizeof(gpu_info.gb_macro_tile_mode) / sizeof(gpu_info.gb_macro_tile_mode[0]);
+ create_flags.value = 0;
+ create_flags.useTileIndex = 1;
+
+ addr_create_input.chipEngine = CIASICIDGFXENGINE_SOUTHERNISLAND;
+
+ addr_create_input.chipFamily = FAMILY_CZ;
+ addr_create_input.createFlags = create_flags;
+ addr_create_input.callbacks.allocSysMem = alloc_sys_mem;
+ addr_create_input.callbacks.freeSysMem = free_sys_mem;
+ addr_create_input.callbacks.debugPrint = 0;
+ addr_create_input.regValue = reg_value;
+
+ addr_ret = AddrCreate(&addr_create_input, &addr_create_output);
+
+ if (addr_ret != ADDR_OK) {
+ fprintf(stderr, "[%s]failed error =%d\n", __func__, addr_ret);
+ return NULL;
+ }
+
+ return addr_create_output.hLib;
+}
+
+static int amdgpu_init(struct driver *drv)
+{
+ int ret;
+ void *addrlib;
+ struct format_metadata metadata;
+ uint32_t flags = BO_USE_RENDER_MASK;
+
+ addrlib = amdgpu_addrlib_init(drv_get_fd(drv));
+ if (!addrlib)
+ return -1;
+
+ drv->priv = addrlib;
+
+ ret = drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats),
+ &LINEAR_METADATA, BO_USE_TEXTURE_MASK);
+ if (ret)
+ return ret;
+
+ drv_modify_combination(drv, DRM_FORMAT_NV21, &LINEAR_METADATA, BO_USE_SCANOUT);
+ drv_modify_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA, BO_USE_SCANOUT);
+
+ metadata.tiling = ADDR_DISPLAYABLE << 16 | ADDR_TM_LINEAR_ALIGNED;
+ metadata.priority = 2;
+ metadata.modifier = DRM_FORMAT_MOD_NONE;
+
+ ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+ &metadata, flags);
+ if (ret)
+ return ret;
+
+ 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_XBGR8888, &metadata, BO_USE_SCANOUT);
+
+ metadata.tiling = ADDR_NON_DISPLAYABLE << 16 | ADDR_TM_LINEAR_ALIGNED;
+ metadata.priority = 3;
+ metadata.modifier = DRM_FORMAT_MOD_NONE;
+
+ ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+ &metadata, flags);
+ if (ret)
+ return ret;
+
+ flags &= ~BO_USE_SW_WRITE_OFTEN;
+ flags &= ~BO_USE_SW_READ_OFTEN;
+ flags &= ~BO_USE_LINEAR;
+
+ metadata.tiling = ADDR_DISPLAYABLE << 16 | ADDR_TM_2D_TILED_THIN1;
+ metadata.priority = 4;
+
+ ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+ &metadata, flags);
+ if (ret)
+ return ret;
+
+ drv_modify_combination(drv, DRM_FORMAT_ARGB8888, &metadata, BO_USE_SCANOUT);
+ drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_SCANOUT);
+ drv_modify_combination(drv, DRM_FORMAT_XBGR8888, &metadata, BO_USE_SCANOUT);
+
+ metadata.tiling = ADDR_NON_DISPLAYABLE << 16 | ADDR_TM_2D_TILED_THIN1;
+ metadata.priority = 5;
+
+ ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+ &metadata, flags);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+static void amdgpu_close(struct driver *drv)
+{
+ AddrDestroy(drv->priv);
+ drv->priv = NULL;
+}
+
+static int amdgpu_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+ uint32_t usage)
+{
+ void *addrlib = bo->drv->priv;
+ union drm_amdgpu_gem_create gem_create;
+ struct amdgpu_bo_metadata metadata = { 0 };
+ ADDR_COMPUTE_SURFACE_INFO_OUTPUT addr_out = { 0 };
+ uint32_t tiling_flags = 0;
+ uint32_t gem_create_flags = 0;
+ size_t plane;
+ int ret;
+
+ if (format == DRM_FORMAT_NV12 || format == DRM_FORMAT_NV21) {
+ drv_bo_from_format(bo, ALIGN(width, 64), height, format);
+ } else {
+ if (amdgpu_addrlib_compute(addrlib, width, height, format, usage, &tiling_flags,
+ &addr_out) < 0)
+ return -EINVAL;
+
+ bo->tiling = tiling_flags;
+ /* RGB has 1 plane only */
+ bo->offsets[0] = 0;
+ bo->total_size = bo->sizes[0] = addr_out.surfSize;
+ bo->strides[0] = addr_out.pixelPitch * DIV_ROUND_UP(addr_out.pixelBits, 8);
+ }
+
+ if (usage & (BO_USE_CURSOR | BO_USE_LINEAR | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN |
+ BO_USE_SW_WRITE_RARELY | BO_USE_SW_READ_RARELY))
+ gem_create_flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
+ else
+ gem_create_flags |= AMDGPU_GEM_CREATE_NO_CPU_ACCESS;
+
+ memset(&gem_create, 0, sizeof(gem_create));
+
+ gem_create.in.bo_size = bo->total_size;
+ gem_create.in.alignment = addr_out.baseAlign;
+ /* Set the placement. */
+ gem_create.in.domains = AMDGPU_GEM_DOMAIN_VRAM;
+ gem_create.in.domain_flags = gem_create_flags;
+ /* Allocate the buffer with the preferred heap. */
+ ret = drmCommandWriteRead(drv_get_fd(bo->drv), DRM_AMDGPU_GEM_CREATE, &gem_create,
+ sizeof(gem_create));
+
+ if (ret < 0)
+ return ret;
+
+ metadata.tiling_info = tiling_flags;
+
+ for (plane = 0; plane < bo->num_planes; plane++)
+ bo->handles[plane].u32 = gem_create.out.handle;
+
+ ret = amdgpu_set_metadata(drv_get_fd(bo->drv), bo->handles[0].u32, &metadata);
+
+ return ret;
+}
+
+static void *amdgpu_bo_map(struct bo *bo, struct map_info *data, size_t plane, int prot)
+{
+ int ret;
+ union drm_amdgpu_gem_mmap gem_map;
+
+ memset(&gem_map, 0, sizeof(gem_map));
+ gem_map.in.handle = bo->handles[plane].u32;
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_AMDGPU_GEM_MMAP, &gem_map);
+ if (ret) {
+ fprintf(stderr, "drv: DRM_IOCTL_AMDGPU_GEM_MMAP failed\n");
+ return MAP_FAILED;
+ }
+ data->length = bo->total_size;
+
+ return mmap(0, bo->total_size, prot, MAP_SHARED, bo->drv->fd, gem_map.out.addr_ptr);
+}
+
+static uint32_t amdgpu_resolve_format(uint32_t format, uint64_t usage)
+{
+ switch (format) {
+ case DRM_FORMAT_FLEX_YCbCr_420_888:
+ return DRM_FORMAT_NV12;
+ default:
+ return format;
+ }
+}
+
+struct backend backend_amdgpu = {
+ .name = "amdgpu",
+ .init = amdgpu_init,
+ .close = amdgpu_close,
+ .bo_create = amdgpu_bo_create,
+ .bo_destroy = drv_gem_bo_destroy,
+ .bo_import = drv_prime_bo_import,
+ .bo_map = amdgpu_bo_map,
+ .resolve_format = amdgpu_resolve_format,
+};
+
+#endif
diff --git a/chromium/third_party/minigbm/src/cirrus.c b/chromium/third_party/minigbm/src/cirrus.c
new file mode 100644
index 00000000000..4f0e983538d
--- /dev/null
+++ b/chromium/third_party/minigbm/src/cirrus.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+const static uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_RGB888,
+ DRM_FORMAT_XRGB8888 };
+
+static int cirrus_init(struct driver *drv)
+{
+ int ret;
+ ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+ &LINEAR_METADATA, BO_USE_RENDER_MASK);
+ if (ret)
+ return ret;
+
+ return drv_modify_linear_combinations(drv);
+}
+
+struct backend backend_cirrus = {
+ .name = "cirrus",
+ .init = cirrus_init,
+ .bo_create = drv_dumb_bo_create,
+ .bo_destroy = drv_dumb_bo_destroy,
+ .bo_import = drv_prime_bo_import,
+ .bo_map = drv_dumb_bo_map,
+};
diff --git a/chromium/third_party/minigbm/src/common.mk b/chromium/third_party/minigbm/src/common.mk
new file mode 100644
index 00000000000..3d7e7d4674c
--- /dev/null
+++ b/chromium/third_party/minigbm/src/common.mk
@@ -0,0 +1,931 @@
+# Copyright 2012 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.
+#
+# If this file is part of another source distribution, it's license may be
+# stored in LICENSE.makefile or LICENSE.common.mk.
+#
+# NOTE NOTE NOTE
+# The authoritative common.mk is located in:
+# https://chromium.googlesource.com/chromiumos/platform2/+/master/common-mk
+# Please make all changes there, then copy into place in other repos.
+# NOTE NOTE NOTE
+#
+# This file provides a common architecture for building C/C++ source trees.
+# It uses recursive makefile inclusion to create a single make process which
+# can be built in the source tree or with the build artifacts placed elsewhere.
+#
+# It is fully parallelizable for all targets, including static archives.
+#
+# To use:
+# 1. Place common.mk in your top source level
+# 2. In your top-level Makefile, place "include common.mk" at the top
+# 3. In all subdirectories, create a 'module.mk' file that starts with:
+# include common.mk
+# And then contains the remainder of your targets.
+# 4. All build targets should look like:
+# relative/path/target: relative/path/obj.o
+#
+# See existing makefiles for rule examples.
+#
+# Exported macros:
+# - cc_binary, cxx_binary provide standard compilation steps for binaries
+# - cxx_library, cc_library provide standard compilation steps for
+# shared objects.
+# All of the above optionally take an argument for extra flags.
+# - update_archive creates/updates a given .a target
+#
+# Instead of using the build macros, most users can just use wrapped targets:
+# - CXX_BINARY, CC_BINARY, CC_STATIC_BINARY, CXX_STATIC_BINARY
+# - CXX_LIBRARY, CC_LIBRARY, CC_STATIC_LIBRARY, CXX_STATIC_LIBRARY
+# - E.g., CXX_BINARY(mahbinary): foo.o
+# - object.depends targets may be used when a prerequisite is required for an
+# object file. Because object files result in multiple build artifacts to
+# handle PIC and PIE weirdness. E.g.
+# foo.o.depends: generated/dbus.h
+# - TEST(binary) or TEST(CXX_BINARY(binary)) may be used as a prerequisite
+# for the tests target to trigger an automated test run.
+# - CLEAN(file_or_dir) dependency can be added to 'clean'.
+#
+# If source code is being generated, rules will need to be registered for
+# compiling the objects. This can be done by adding one of the following
+# to the Makefile:
+# - For C source files
+# $(eval $(call add_object_rules,sub/dir/gen_a.o sub/dir/b.o,CC,c,CFLAGS))
+# - For C++ source files
+# $(eval $(call add_object_rules,sub/dir/gen_a.o sub/dir/b.o,CXX,cc,CXXFLAGS))
+#
+# Exported targets meant to have prerequisites added to:
+# - all - Your desired targets should be given
+# - tests - Any TEST(test_binary) targets should be given
+# - FORCE - force the given target to run regardless of changes
+# In most cases, using .PHONY is preferred.
+#
+# Possible command line variables:
+# - COLOR=[0|1] to set ANSI color output (default: 1)
+# - VERBOSE=[0|1] to hide/show commands (default: 0)
+# - MODE=[opt|dbg|profiling] (default: opt)
+# opt - Enable optimizations for release builds
+# dbg - Turn down optimization for debugging
+# profiling - Turn off optimization and turn on profiling/coverage
+# support.
+# - ARCH=[x86|arm|supported qemu name] (default: from portage or uname -m)
+# - SPLITDEBUG=[0|1] splits debug info in target.debug (default: 0)
+# If NOSTRIP=1, SPLITDEBUG will never strip the final emitted objects.
+# - NOSTRIP=[0|1] determines if binaries are stripped. (default: 1)
+# NOSTRIP=0 and MODE=opt will also drop -g from the CFLAGS.
+# - VALGRIND=[0|1] runs tests under valgrind (default: 0)
+# - OUT=/path/to/builddir puts all output in given path (default: $PWD)
+# - VALGRIND_ARGS="" supplies extra memcheck arguments
+#
+# Per-target(-ish) variable:
+# - NEEDS_ROOT=[0|1] allows a TEST() target to run with root.
+# Default is 0 unless it is running under QEmu.
+# - NEEDS_MOUNTS=[0|1] allows a TEST() target running on QEmu to get
+# setup mounts in the $(SYSROOT)
+#
+# Caveats:
+# - Directories or files with spaces in them DO NOT get along with GNU Make.
+# If you need them, all uses of dir/notdir/etc will need to have magic
+# wrappers. Proceed at risk to your own sanity.
+# - External CXXFLAGS and CFLAGS should be passed via the environment since
+# this file does not use 'override' to control them.
+# - Our version of GNU Make doesn't seem to support the 'private' variable
+# annotation, so you can't tag a variable private on a wrapping target.
+
+# Behavior configuration variables
+SPLITDEBUG ?= 0
+NOSTRIP ?= 1
+VALGRIND ?= 0
+COLOR ?= 1
+VERBOSE ?= 0
+MODE ?= opt
+CXXEXCEPTIONS ?= 0
+ARCH ?= $(shell uname -m)
+
+# Put objects in a separate tree based on makefile locations
+# This means you can build a tree without touching it:
+# make -C $SRCDIR # will create ./build-$(MODE)
+# Or
+# make -C $SRCDIR OUT=$PWD
+# This variable is extended on subdir calls and doesn't need to be re-called.
+OUT ?= $(PWD)/
+
+# Make OUT now so we can use realpath.
+$(shell mkdir -p "$(OUT)")
+
+# TODO(wad) Relative paths are resolved against SRC and not the calling dir.
+# Ensure a command-line supplied OUT has a slash
+override OUT := $(realpath $(OUT))/
+
+# SRC is not meant to be set by the end user, but during make call relocation.
+# $(PWD) != $(CURDIR) all the time.
+export SRC ?= $(CURDIR)
+
+# Re-start in the $(OUT) directory if we're not there.
+# We may be invoked using -C or bare and we need to ensure behavior
+# is consistent so we check both PWD vs OUT and PWD vs CURDIR.
+override RELOCATE_BUILD := 0
+ifneq (${PWD}/,${OUT})
+override RELOCATE_BUILD := 1
+endif
+# Make sure we're running with no builtin targets. They cause
+# leakage and mayhem!
+ifneq (${PWD},${CURDIR})
+override RELOCATE_BUILD := 1
+# If we're run from the build dir, don't let it get cleaned up later.
+ifeq (${PWD}/,${OUT})
+$(shell touch "$(PWD)/.dont_delete_on_clean")
+endif
+endif # ifneq (${PWD},${CURDIR}
+
+# "Relocate" if we need to restart without implicit rules.
+ifeq ($(subst r,,$(MAKEFLAGS)),$(MAKEFLAGS))
+override RELOCATE_BUILD := 1
+endif
+
+ifeq (${RELOCATE_BUILD},1)
+# By default, silence build output. Reused below as well.
+QUIET = @
+ifeq ($(VERBOSE),1)
+ QUIET=
+endif
+
+# This target will override all targets, including prerequisites. To avoid
+# calling $(MAKE) once per prereq on the given CMDGOAL, we guard it with a local
+# variable.
+RUN_ONCE := 0
+MAKECMDGOALS ?= all
+# Keep the rules split as newer make does not allow them to be declared
+# on the same line. But the way :: rules work, the _all here will also
+# invoke the %:: rule while retaining "_all" as the default.
+_all::
+%::
+ $(if $(filter 0,$(RUN_ONCE)), \
+ cd "$(OUT)" && \
+ $(MAKE) -r -I "$(SRC)" -f "$(CURDIR)/Makefile" \
+ SRC="$(CURDIR)" OUT="$(OUT)" $(foreach g,$(MAKECMDGOALS),"$(g)"),)
+ $(eval RUN_ONCE := 1)
+pass-to-subcall := 1
+endif
+
+ifeq ($(pass-to-subcall),)
+
+# Only call MODULE if we're in a submodule
+MODULES_LIST := $(filter-out Makefile %.d,$(MAKEFILE_LIST))
+ifeq ($(words $(filter-out Makefile common.mk %.d $(SRC)/Makefile \
+ $(SRC)/common.mk,$(MAKEFILE_LIST))),0)
+
+# All the top-level defines outside of module.mk.
+
+#
+# Helper macros
+#
+
+# Create the directory if it doesn't yet exist.
+define auto_mkdir
+ $(if $(wildcard $(dir $1)),$2,$(QUIET)mkdir -p "$(dir $1)")
+endef
+
+# Creates the actual archive with an index.
+# The target $@ must end with .pic.a or .pie.a.
+define update_archive
+ $(call auto_mkdir,$(TARGET_OR_MEMBER))
+ $(QUIET)# Create the archive in one step to avoid parallel use accessing it
+ $(QUIET)# before all the symbols are present.
+ @$(ECHO) "AR $(subst \
+$(SRC)/,,$(^:.o=$(suffix $(basename $(TARGET_OR_MEMBER))).o)) \
+-> $(subst $(SRC)/,,$(TARGET_OR_MEMBER))"
+ $(QUIET)$(AR) rcs $(TARGET_OR_MEMBER) \
+ $(subst $(SRC)/,,$(^:.o=$(suffix $(basename $(TARGET_OR_MEMBER))).o))
+endef
+
+# Default compile from objects using pre-requisites but filters out
+# subdirs and .d files.
+define cc_binary
+ $(call COMPILE_BINARY_implementation,CC,$(CFLAGS) $(1),$(EXTRA_FLAGS))
+endef
+
+define cxx_binary
+ $(call COMPILE_BINARY_implementation,CXX,$(CXXFLAGS) $(1),$(EXTRA_FLAGS))
+endef
+
+# Default compile from objects using pre-requisites but filters out
+# subdirs and .d files.
+define cc_library
+ $(call COMPILE_LIBRARY_implementation,CC,$(CFLAGS) $(1),$(EXTRA_FLAGS))
+endef
+define cxx_library
+ $(call COMPILE_LIBRARY_implementation,CXX,$(CXXFLAGS) $(1),$(EXTRA_FLAGS))
+endef
+
+# Deletes files silently if they exist. Meant for use in any local
+# clean targets.
+define silent_rm
+ $(if $(wildcard $(1)),
+ $(QUIET)($(ECHO) -n '$(COLOR_RED)CLEANFILE$(COLOR_RESET) ' && \
+ $(ECHO) '$(subst $(OUT)/,,$(wildcard $(1)))' && \
+ $(RM) $(1) 2>/dev/null) || true,)
+endef
+define silent_rmdir
+ $(if $(wildcard $(1)),
+ $(if $(wildcard $(1)/*),
+ $(QUIET)# $(1) not empty [$(wildcard $(1)/*)]. Not deleting.,
+ $(QUIET)($(ECHO) -n '$(COLOR_RED)CLEANDIR$(COLOR_RESET) ' && \
+ $(ECHO) '$(subst $(OUT)/,,$(wildcard $(1)))' && \
+ $(RMDIR) $(1) 2>/dev/null) || true),)
+endef
+
+#
+# Default variable values
+#
+
+# Only override toolchain vars if they are from make.
+CROSS_COMPILE ?=
+define override_var
+ifneq ($(filter undefined default,$(origin $1)),)
+$1 = $(CROSS_COMPILE)$2
+endif
+endef
+$(eval $(call override_var,AR,ar))
+$(eval $(call override_var,CC,gcc))
+$(eval $(call override_var,CXX,g++))
+$(eval $(call override_var,OBJCOPY,objcopy))
+$(eval $(call override_var,PKG_CONFIG,pkg-config))
+$(eval $(call override_var,RANLIB,ranlib))
+$(eval $(call override_var,STRIP,strip))
+
+RMDIR ?= rmdir
+ECHO = /bin/echo -e
+
+ifeq ($(lastword $(subst /, ,$(CC))),clang)
+CDRIVER = clang
+else
+CDRIVER = gcc
+endif
+
+ifeq ($(lastword $(subst /, ,$(CXX))),clang++)
+CXXDRIVER = clang
+else
+CXXDRIVER = gcc
+endif
+
+# Internal macro to support check_XXX macros below.
+# Usage: $(call check_compile, [code], [compiler], [code_type], [c_flags],
+# [extra_c_flags], [library_flags], [success_ret], [fail_ret])
+# Return: [success_ret] if compile succeeded, otherwise [fail_ret]
+check_compile = $(shell printf '%b\n' $(1) | \
+ $($(2)) $($(4)) -x $(3) $(LDFLAGS) $(5) - $(6) -o /dev/null > /dev/null 2>&1 \
+ && echo "$(7)" || echo "$(8)")
+
+# Helper macro to check whether a test program will compile with the specified
+# compiler flags.
+# Usage: $(call check_compile_cc, [code], [flags], [alternate_flags])
+# Return: [flags] if compile succeeded, otherwise [alternate_flags]
+check_compile_cc = $(call check_compile,$(1),CC,c,CFLAGS,$(2),,$(2),$(3))
+check_compile_cxx = $(call check_compile,$(1),CXX,c++,CXXFLAGS,$(2),,$(2),$(3))
+
+# Helper macro to check whether a test program will compile with the specified
+# libraries.
+# Usage: $(call check_compile_cc, [code], [library_flags], [alternate_flags])
+# Return: [library_flags] if compile succeeded, otherwise [alternate_flags]
+check_libs_cc = $(call check_compile,$(1),CC,c,CFLAGS,,$(2),$(2),$(3))
+check_libs_cxx = $(call check_compile,$(1),CXX,c++,CXXFLAGS,,$(2),$(2),$(3))
+
+# Helper macro to check whether the compiler accepts the specified flags.
+# Usage: $(call check_compile_cc, [flags], [alternate_flags])
+# Return: [flags] if compile succeeded, otherwise [alternate_flags]
+check_cc = $(call check_compile_cc,'int main() { return 0; }',$(1),$(2))
+check_cxx = $(call check_compile_cxx,'int main() { return 0; }',$(1),$(2))
+
+# Choose the stack protector flags based on whats supported by the compiler.
+SSP_CFLAGS := $(call check_cc,-fstack-protector-strong)
+ifeq ($(SSP_CFLAGS),)
+ SSP_CFLAGS := $(call check_cc,-fstack-protector-all)
+endif
+
+# To update these from an including Makefile:
+# CXXFLAGS += -mahflag # Append to the list
+# CXXFLAGS := -mahflag $(CXXFLAGS) # Prepend to the list
+# CXXFLAGS := $(filter-out badflag,$(CXXFLAGS)) # Filter out a value
+# The same goes for CFLAGS.
+COMMON_CFLAGS-gcc := -fvisibility=internal -ggdb3 -Wa,--noexecstack
+COMMON_CFLAGS-clang := -fvisibility=hidden -ggdb
+COMMON_CFLAGS := -Wall -Werror -fno-strict-aliasing $(SSP_CFLAGS) -O1 -Wformat=2
+CXXFLAGS += $(COMMON_CFLAGS) $(COMMON_CFLAGS-$(CXXDRIVER))
+CFLAGS += $(COMMON_CFLAGS) $(COMMON_CFLAGS-$(CDRIVER))
+CPPFLAGS += -D_FORTIFY_SOURCE=2
+
+# Disable exceptions based on the CXXEXCEPTIONS setting.
+ifeq ($(CXXEXCEPTIONS),0)
+ CXXFLAGS := $(CXXFLAGS) -fno-exceptions -fno-unwind-tables \
+ -fno-asynchronous-unwind-tables
+endif
+
+ifeq ($(MODE),opt)
+ # Up the optimizations.
+ CFLAGS := $(filter-out -O1,$(CFLAGS)) -O2
+ CXXFLAGS := $(filter-out -O1,$(CXXFLAGS)) -O2
+ # Only drop -g* if symbols aren't desired.
+ ifeq ($(NOSTRIP),0)
+ # TODO: do we want -fomit-frame-pointer on x86?
+ CFLAGS := $(filter-out -ggdb3,$(CFLAGS))
+ CXXFLAGS := $(filter-out -ggdb3,$(CXXFLAGS))
+ endif
+endif
+
+ifeq ($(MODE),profiling)
+ CFLAGS := $(CFLAGS) -O0 -g --coverage
+ CXXFLAGS := $(CXXFLAGS) -O0 -g --coverage
+ LDFLAGS := $(LDFLAGS) --coverage
+endif
+
+LDFLAGS := $(LDFLAGS) -Wl,-z,relro -Wl,-z,noexecstack -Wl,-z,now
+
+# Fancy helpers for color if a prompt is defined
+ifeq ($(COLOR),1)
+COLOR_RESET = \x1b[0m
+COLOR_GREEN = \x1b[32;01m
+COLOR_RED = \x1b[31;01m
+COLOR_YELLOW = \x1b[33;01m
+endif
+
+# By default, silence build output.
+QUIET = @
+ifeq ($(VERBOSE),1)
+ QUIET=
+endif
+
+#
+# Implementation macros for compile helpers above
+#
+
+# Useful for dealing with pie-broken toolchains.
+# Call make with PIE=0 to disable default PIE use.
+OBJ_PIE_FLAG = -fPIE
+COMPILE_PIE_FLAG = -pie
+ifeq ($(PIE),0)
+ OBJ_PIE_FLAG =
+ COMPILE_PIE_FLAG =
+endif
+
+# Favor member targets first for CXX_BINARY(%) magic.
+# And strip out nested members if possible.
+LP := (
+RP := )
+TARGET_OR_MEMBER = $(lastword $(subst $(LP), ,$(subst $(RP),,$(or $%,$@))))
+
+# Default compile from objects using pre-requisites but filters out
+# all non-.o files.
+define COMPILE_BINARY_implementation
+ @$(ECHO) "LD$(1) $(subst $(PWD)/,,$(TARGET_OR_MEMBER))"
+ $(call auto_mkdir,$(TARGET_OR_MEMBER))
+ $(QUIET)$($(1)) $(COMPILE_PIE_FLAGS) -o $(TARGET_OR_MEMBER) \
+ $(2) $(LDFLAGS) \
+ $(filter %.o %.a,$(^:.o=.pie.o)) \
+ $(foreach so,$(filter %.so,$^),-L$(dir $(so)) \
+ -l$(patsubst lib%,%,$(basename $(notdir $(so))))) \
+ $(LDLIBS)
+ $(call conditional_strip)
+ @$(ECHO) -n "BIN "
+ @$(ECHO) "$(COLOR_GREEN)$(subst $(PWD)/,,$(TARGET_OR_MEMBER))$(COLOR_RESET)"
+ @$(ECHO) " $(COLOR_YELLOW)-----$(COLOR_RESET)"
+endef
+
+# TODO: add version support extracted from PV environment variable
+#ifeq ($(PV),9999)
+#$(warning PV=$(PV). If shared object versions matter, please force PV=.)
+#endif
+# Then add -Wl,-soname,$@.$(PV) ?
+
+# Default compile from objects using pre-requisites but filters out
+# all non-.o values. (Remember to add -L$(OUT) -llib)
+COMMA := ,
+define COMPILE_LIBRARY_implementation
+ @$(ECHO) "SHARED$(1) $(subst $(PWD)/,,$(TARGET_OR_MEMBER))"
+ $(call auto_mkdir,$(TARGET_OR_MEMBER))
+ $(QUIET)$($(1)) -shared -Wl,-E -o $(TARGET_OR_MEMBER) \
+ $(2) $(LDFLAGS) \
+ $(if $(filter %.a,$^),-Wl$(COMMA)--whole-archive,) \
+ $(filter %.o ,$(^:.o=.pic.o)) \
+ $(foreach a,$(filter %.a,$^),-L$(dir $(a)) \
+ -l$(patsubst lib%,%,$(basename $(notdir $(a))))) \
+ $(foreach so,$(filter %.so,$^),-L$(dir $(so)) \
+ -l$(patsubst lib%,%,$(basename $(notdir $(so))))) \
+ $(LDLIBS)
+ $(call conditional_strip)
+ @$(ECHO) -n "LIB $(COLOR_GREEN)"
+ @$(ECHO) "$(subst $(PWD)/,,$(TARGET_OR_MEMBER))$(COLOR_RESET)"
+ @$(ECHO) " $(COLOR_YELLOW)-----$(COLOR_RESET)"
+endef
+
+define conditional_strip
+ $(if $(filter 0,$(NOSTRIP)),$(call strip_artifact))
+endef
+
+define strip_artifact
+ @$(ECHO) "STRIP $(subst $(OUT)/,,$(TARGET_OR_MEMBER))"
+ $(if $(filter 1,$(SPLITDEBUG)), @$(ECHO) -n "DEBUG "; \
+ $(ECHO) "$(COLOR_YELLOW)\
+$(subst $(OUT)/,,$(TARGET_OR_MEMBER)).debug$(COLOR_RESET)")
+ $(if $(filter 1,$(SPLITDEBUG)), \
+ $(QUIET)$(OBJCOPY) --only-keep-debug "$(TARGET_OR_MEMBER)" \
+ "$(TARGET_OR_MEMBER).debug")
+ $(if $(filter-out dbg,$(MODE)),$(QUIET)$(STRIP) --strip-unneeded \
+ "$(TARGET_OR_MEMBER)",)
+endef
+
+#
+# Global pattern rules
+#
+
+# Below, the archive member syntax is abused to create fancier
+# syntactic sugar for recipe authors that avoids needed to know
+# subcall options. The downside is that make attempts to look
+# into the phony archives for timestamps. This will cause the final
+# target to be rebuilt/linked on _every_ call to make even when nothing
+# has changed. Until a better way presents itself, we have helpers that
+# do the stat check on make's behalf. Dodgy but simple.
+define old_or_no_timestamp
+ $(if $(realpath $%),,$(1))
+ $(if $(shell find $^ -cnewer "$%" 2>/dev/null),$(1))
+endef
+
+define check_deps
+ $(if $(filter 0,$(words $^)),\
+ $(error Missing dependencies or declaration of $@($%)),)
+endef
+
+# Build a cxx target magically
+CXX_BINARY(%):
+ $(call check_deps)
+ $(call old_or_no_timestamp,$(call cxx_binary))
+clean: CLEAN(CXX_BINARY*)
+
+CC_BINARY(%):
+ $(call check_deps)
+ $(call old_or_no_timestamp,$(call cc_binary))
+clean: CLEAN(CC_BINARY*)
+
+CXX_STATIC_BINARY(%):
+ $(call check_deps)
+ $(call old_or_no_timestamp,$(call cxx_binary,-static))
+clean: CLEAN(CXX_STATIC_BINARY*)
+
+CC_STATIC_BINARY(%):
+ $(call check_deps)
+ $(call old_or_no_timestamp,$(call cc_binary,-static))
+clean: CLEAN(CC_STATIC_BINARY*)
+
+CXX_LIBRARY(%):
+ $(call check_deps)
+ $(call old_or_no_timestamp,$(call cxx_library))
+clean: CLEAN(CXX_LIBRARY*)
+
+CXX_LIBARY(%):
+ $(error Typo alert! LIBARY != LIBRARY)
+
+CC_LIBRARY(%):
+ $(call check_deps)
+ $(call old_or_no_timestamp,$(call cc_library))
+clean: CLEAN(CC_LIBRARY*)
+
+CC_LIBARY(%):
+ $(error Typo alert! LIBARY != LIBRARY)
+
+CXX_STATIC_LIBRARY(%):
+ $(call check_deps)
+ $(call old_or_no_timestamp,$(call update_archive))
+clean: CLEAN(CXX_STATIC_LIBRARY*)
+
+CXX_STATIC_LIBARY(%):
+ $(error Typo alert! LIBARY != LIBRARY)
+
+CC_STATIC_LIBRARY(%):
+ $(call check_deps)
+ $(call old_or_no_timestamp,$(call update_archive))
+clean: CLEAN(CC_STATIC_LIBRARY*)
+
+CC_STATIC_LIBARY(%):
+ $(error Typo alert! LIBARY != LIBRARY)
+
+
+TEST(%): % qemu_chroot_install
+ $(call TEST_implementation)
+.PHONY: TEST
+
+# multiple targets with a wildcard need to share an directory.
+# Don't use this directly it just makes sure the directory is removed _after_
+# the files are.
+CLEANFILE(%):
+ $(call silent_rm,$(TARGET_OR_MEMBER))
+.PHONY: CLEANFILE
+
+CLEAN(%): CLEANFILE(%)
+ $(QUIET)# CLEAN($%) meta-target called
+ $(if $(filter-out $(PWD)/,$(dir $(abspath $(TARGET_OR_MEMBER)))), \
+ $(call silent_rmdir,$(dir $(abspath $(TARGET_OR_MEMBER)))),\
+ $(QUIET)# Not deleting $(dir $(abspath $(TARGET_OR_MEMBER))) yet.)
+.PHONY: CLEAN
+
+#
+# Top-level objects and pattern rules
+#
+
+# All objects for .c files at the top level
+C_OBJECTS = $(patsubst $(SRC)/%.c,%.o,$(wildcard $(SRC)/*.c))
+
+
+# All objects for .cxx files at the top level
+CXX_OBJECTS = $(patsubst $(SRC)/%.cc,%.o,$(wildcard $(SRC)/*.cc))
+
+# Note, the catch-all pattern rules don't work in subdirectories because
+# we're building from the $(OUT) directory. At the top-level (here) they will
+# work, but we go ahead and match using the module form. Then we can place a
+# generic pattern rule to capture leakage from the main Makefile. (Later in the
+# file.)
+#
+# The reason target specific pattern rules work well for modules,
+# MODULE_C_OBJECTS, is because it scopes the behavior to the given target which
+# ensures we get a relative directory offset from $(OUT) which otherwise would
+# not match without further magic on a per-subdirectory basis.
+
+# Creates object file rules. Call with eval.
+# $(1) list of .o files
+# $(2) source type (CC or CXX)
+# $(3) source suffix (cc or c)
+# $(4) compiler flag name (CFLAGS or CXXFLAGS)
+# $(5) source dir: _only_ if $(SRC). Leave blank for obj tree.
+define add_object_rules
+$(patsubst %.o,%.pie.o,$(1)): %.pie.o: $(5)%.$(3) %.o.depends
+ $$(call auto_mkdir,$$@)
+ $$(call OBJECT_PATTERN_implementation,$(2),\
+ $$(basename $$@),$$($(4)) $$(CPPFLAGS) $$(OBJ_PIE_FLAG))
+
+$(patsubst %.o,%.pic.o,$(1)): %.pic.o: $(5)%.$(3) %.o.depends
+ $$(call auto_mkdir,$$@)
+ $$(call OBJECT_PATTERN_implementation,$(2),\
+ $$(basename $$@),$$($(4)) $$(CPPFLAGS) -fPIC)
+
+# Placeholder for depends
+$(patsubst %.o,%.o.depends,$(1)):
+ $$(call auto_mkdir,$$@)
+ $$(QUIET)touch "$$@"
+
+$(1): %.o: %.pic.o %.pie.o
+ $$(call auto_mkdir,$$@)
+ $$(QUIET)touch "$$@"
+endef
+
+define OBJECT_PATTERN_implementation
+ @$(ECHO) "$(1) $(subst $(SRC)/,,$<) -> $(2).o"
+ $(call auto_mkdir,$@)
+ $(QUIET)$($(1)) -c -MD -MF $(2).d $(3) -o $(2).o $<
+ $(QUIET)# Wrap all the deps in $$(wildcard) so a missing header
+ $(QUIET)# won't cause weirdness. First we remove newlines and \,
+ $(QUIET)# then wrap it.
+ $(QUIET)sed -i -e :j -e '$$!N;s|\\\s*\n| |;tj' \
+ -e 's|^\(.*\s*:\s*\)\(.*\)$$|\1 $$\(wildcard \2\)|' $(2).d
+endef
+
+# Now actually register handlers for C(XX)_OBJECTS.
+$(eval $(call add_object_rules,$(C_OBJECTS),CC,c,CFLAGS,$(SRC)/))
+$(eval $(call add_object_rules,$(CXX_OBJECTS),CXX,cc,CXXFLAGS,$(SRC)/))
+
+# Disable default pattern rules to help avoid leakage.
+# These may already be handled by '-r', but let's keep it to be safe.
+%: %.o ;
+%.a: %.o ;
+%.o: %.c ;
+%.o: %.cc ;
+
+# NOTE: A specific rule for archive objects is avoided because parallel
+# update of the archive causes build flakiness.
+# Instead, just make the objects the prerequisites and use update_archive
+# To use the foo.a(obj.o) functionality, targets would need to specify the
+# explicit object they expect on the prerequisite line.
+
+#
+# Architecture detection and QEMU wrapping
+#
+
+HOST_ARCH ?= $(shell uname -m)
+override ARCH := $(strip $(ARCH))
+override HOST_ARCH := $(strip $(HOST_ARCH))
+# emake will supply "x86" or "arm" for ARCH, but
+# if uname -m runs and you get x86_64, then this subst
+# will break.
+ifeq ($(subst x86,i386,$(ARCH)),i386)
+ QEMU_ARCH := $(subst x86,i386,$(ARCH)) # x86 -> i386
+else ifeq ($(subst amd64,x86_64,$(ARCH)),x86_64)
+ QEMU_ARCH := $(subst amd64,x86_64,$(ARCH)) # amd64 -> x86_64
+else
+ QEMU_ARCH = $(ARCH)
+endif
+override QEMU_ARCH := $(strip $(QEMU_ARCH))
+
+# If we're cross-compiling, try to use qemu for running the tests.
+ifneq ($(QEMU_ARCH),$(HOST_ARCH))
+ ifeq ($(SYSROOT),)
+ $(info SYSROOT not defined. qemu-based testing disabled)
+ else
+ # A SYSROOT is assumed for QEmu use.
+ USE_QEMU ?= 1
+
+ # Allow 64-bit hosts to run 32-bit without qemu.
+ ifeq ($(HOST_ARCH),x86_64)
+ ifeq ($(QEMU_ARCH),i386)
+ USE_QEMU = 0
+ endif
+ endif
+ endif
+else
+ USE_QEMU ?= 0
+endif
+
+# Normally we don't need to run as root or do bind mounts, so only
+# enable it by default when we're using QEMU.
+NEEDS_ROOT ?= $(USE_QEMU)
+NEEDS_MOUNTS ?= $(USE_QEMU)
+
+SYSROOT_OUT = $(OUT)
+ifneq ($(SYSROOT),)
+ SYSROOT_OUT = $(subst $(SYSROOT),,$(OUT))
+else
+ # Default to / when all the empty-sysroot logic is done.
+ SYSROOT = /
+endif
+
+QEMU_NAME = qemu-$(QEMU_ARCH)
+QEMU_PATH = /build/bin/$(QEMU_NAME)
+QEMU_SYSROOT_PATH = $(SYSROOT)$(QEMU_PATH)
+QEMU_SRC_PATH = /usr/bin/$(QEMU_NAME)
+QEMU_BINFMT_PATH = /proc/sys/fs/binfmt_misc/$(QEMU_NAME)
+QEMU_REGISTER_PATH = /proc/sys/fs/binfmt_misc/register
+
+QEMU_MAGIC_arm = ":$(QEMU_NAME):M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/build/bin/qemu-arm:"
+
+
+#
+# Output full configuration at top level
+#
+
+# Don't show on clean
+ifneq ($(MAKECMDGOALS),clean)
+ $(info build configuration:)
+ $(info - OUT=$(OUT))
+ $(info - SRC=$(SRC))
+ $(info - MODE=$(MODE))
+ $(info - SPLITDEBUG=$(SPLITDEBUG))
+ $(info - NOSTRIP=$(NOSTRIP))
+ $(info - VALGRIND=$(VALGRIND))
+ $(info - COLOR=$(COLOR))
+ $(info - CXXEXCEPTIONS=$(CXXEXCEPTIONS))
+ $(info - ARCH=$(ARCH))
+ $(info - QEMU_ARCH=$(QEMU_ARCH))
+ $(info - USE_QEMU=$(USE_QEMU))
+ $(info - NEEDS_ROOT=$(NEEDS_ROOT))
+ $(info - NEEDS_MOUNTS=$(NEEDS_MOUNTS))
+ $(info - SYSROOT=$(SYSROOT))
+ $(info )
+endif
+
+#
+# Standard targets with detection for when they are improperly configured.
+#
+
+# all does not include tests by default
+all:
+ $(QUIET)(test -z "$^" && \
+ $(ECHO) "You must add your targets as 'all' prerequisites") || true
+ $(QUIET)test -n "$^"
+
+# Builds and runs tests for the target arch
+# Run them in parallel
+# After the test have completed, if profiling, run coverage analysis
+tests:
+ifeq ($(MODE),profiling)
+ @$(ECHO) "COVERAGE [$(COLOR_YELLOW)STARTED$(COLOR_RESET)]"
+ $(QUIET)FILES=""; \
+ for GCNO in `find . -name "*.gcno"`; do \
+ GCDA="$${GCNO%.gcno}.gcda"; \
+ if [ -e $${GCDA} ]; then \
+ FILES="$${FILES} $${GCDA}"; \
+ fi \
+ done; \
+ if [ -n "$${FILES}" ]; then \
+ gcov -l $${FILES}; \
+ lcov --capture --directory . \
+ --output-file=lcov-coverage.info; \
+ genhtml lcov-coverage.info \
+ --output-directory lcov-html; \
+ fi
+ @$(ECHO) "COVERAGE [$(COLOR_YELLOW)FINISHED$(COLOR_RESET)]"
+endif
+.PHONY: tests
+
+qemu_chroot_install:
+ifeq ($(USE_QEMU),1)
+ $(QUIET)$(ECHO) "QEMU Preparing $(QEMU_NAME)"
+ @# Copying strategy
+ @# Compare /usr/bin/qemu inode to /build/$board/build/bin/qemu, if different
+ @# hard link to a temporary file, then rename temp to target. This should
+ @# ensure that once $QEMU_SYSROOT_PATH exists it will always exist, regardless
+ @# of simultaneous test setups.
+ $(QUIET)if [[ ! -e $(QEMU_SYSROOT_PATH) || \
+ `stat -c %i $(QEMU_SRC_PATH)` != `stat -c %i $(QEMU_SYSROOT_PATH)` \
+ ]]; then \
+ $(ROOT_CMD) ln -Tf $(QEMU_SRC_PATH) $(QEMU_SYSROOT_PATH).$$$$; \
+ $(ROOT_CMD) mv -Tf $(QEMU_SYSROOT_PATH).$$$$ $(QEMU_SYSROOT_PATH); \
+ fi
+
+ @# Prep the binfmt handler. First mount if needed, then unregister any bad
+ @# mappings and then register our mapping.
+ @# There may still be some race conditions here where one script de-registers
+ @# and another script starts executing before it gets re-registered, however
+ @# it should be rare.
+ -$(QUIET)[[ -e $(QEMU_REGISTER_PATH) ]] || \
+ $(ROOT_CMD) mount binfmt_misc -t binfmt_misc \
+ /proc/sys/fs/binfmt_misc
+
+ -$(QUIET)if [[ -e $(QEMU_BINFMT_PATH) && \
+ `awk '$$1 == "interpreter" {print $$NF}' $(QEMU_BINFMT_PATH)` != \
+ "$(QEMU_PATH)" ]]; then \
+ echo -1 | $(ROOT_CMD) tee $(QEMU_BINFMT_PATH) >/dev/null; \
+ fi
+
+ -$(if $(QEMU_MAGIC_$(ARCH)),$(QUIET)[[ -e $(QEMU_BINFMT_PATH) ]] || \
+ echo $(QEMU_MAGIC_$(ARCH)) | $(ROOT_CMD) tee $(QEMU_REGISTER_PATH) \
+ >/dev/null)
+endif
+.PHONY: qemu_clean qemu_chroot_install
+
+# TODO(wad) Move to -L $(SYSROOT) and fakechroot when qemu-user
+# doesn't hang traversing /proc from SYSROOT.
+SUDO_CMD = sudo
+UNSHARE_CMD = unshare
+QEMU_CMD =
+ROOT_CMD = $(if $(filter 1,$(NEEDS_ROOT)),$(SUDO_CMD) , )
+MOUNT_CMD = $(if $(filter 1,$(NEEDS_MOUNTS)),$(ROOT_CMD) mount, \#)
+UMOUNT_CMD = $(if $(filter 1,$(NEEDS_MOUNTS)),$(ROOT_CMD) umount, \#)
+QEMU_LDPATH = $(SYSROOT_LDPATH):/lib64:/lib:/usr/lib64:/usr/lib
+ROOT_CMD_LDPATH = $(SYSROOT_LDPATH):$(SYSROOT)/lib64:
+ROOT_CMD_LDPATH := $(ROOT_CMD_LDPATH):$(SYSROOT)/lib:$(SYSROOT)/usr/lib64:
+ROOT_CMD_LDPATH := $(ROOT_CMD_LDPATH):$(SYSROOT)/usr/lib
+ifeq ($(USE_QEMU),1)
+ export QEMU_CMD = \
+ $(SUDO_CMD) chroot $(SYSROOT) $(QEMU_PATH) \
+ -drop-ld-preload \
+ -E LD_LIBRARY_PATH="$(QEMU_LDPATH):$(patsubst $(OUT),,$(LD_DIRS))" \
+ -E HOME="$(HOME)" -E SRC="$(SRC)" --
+ # USE_QEMU conditional function
+ define if_qemu
+ $(1)
+ endef
+else
+ ROOT_CMD = $(if $(filter 1,$(NEEDS_ROOT)),sudo, ) \
+ LD_LIBRARY_PATH="$(ROOT_CMD_LDPATH):$(LD_DIRS)"
+ define if_qemu
+ $(2)
+ endef
+endif
+
+VALGRIND_CMD =
+ifeq ($(VALGRIND),1)
+ VALGRIND_CMD = /usr/bin/valgrind --tool=memcheck $(VALGRIND_ARGS) --
+endif
+
+define TEST_implementation
+ $(QUIET)$(call TEST_setup)
+ $(QUIET)$(call TEST_run)
+ $(QUIET)$(call TEST_teardown)
+ $(QUIET)exit $$(cat $(OUT)$(TARGET_OR_MEMBER).status.test)
+endef
+
+define TEST_setup
+ @$(ECHO) -n "TEST $(TARGET_OR_MEMBER) "
+ @$(ECHO) "[$(COLOR_YELLOW)SETUP$(COLOR_RESET)]"
+ $(QUIET)# Setup a target-specific results file
+ $(QUIET)(echo > $(OUT)$(TARGET_OR_MEMBER).setup.test)
+ $(QUIET)(echo 1 > $(OUT)$(TARGET_OR_MEMBER).status.test)
+ $(QUIET)(echo > $(OUT)$(TARGET_OR_MEMBER).cleanup.test)
+ $(QUIET)# No setup if we are not using QEMU
+ $(QUIET)# TODO(wad) this is racy until we use a vfs namespace
+ $(call if_qemu,\
+ $(QUIET)(echo "mkdir -p '$(SYSROOT)/proc' '$(SYSROOT)/dev' \
+ '$(SYSROOT)/mnt/host/source'" \
+ >> "$(OUT)$(TARGET_OR_MEMBER).setup.test"))
+ $(call if_qemu,\
+ $(QUIET)(echo "$(MOUNT_CMD) --bind /mnt/host/source \
+ '$(SYSROOT)/mnt/host/source'" \
+ >> "$(OUT)$(TARGET_OR_MEMBER).setup.test"))
+ $(call if_qemu,\
+ $(QUIET)(echo "$(MOUNT_CMD) --bind /proc '$(SYSROOT)/proc'" \
+ >> "$(OUT)$(TARGET_OR_MEMBER).setup.test"))
+ $(call if_qemu,\
+ $(QUIET)(echo "$(MOUNT_CMD) --bind /dev '$(SYSROOT)/dev'" \
+ >> "$(OUT)$(TARGET_OR_MEMBER).setup.test"))
+endef
+
+define TEST_teardown
+ @$(ECHO) -n "TEST $(TARGET_OR_MEMBER) "
+ @$(ECHO) "[$(COLOR_YELLOW)TEARDOWN$(COLOR_RESET)]"
+ $(call if_qemu, $(QUIET)$(SHELL) "$(OUT)$(TARGET_OR_MEMBER).cleanup.test")
+endef
+
+# Use GTEST_ARGS.[arch] if defined.
+override GTEST_ARGS.real = \
+ $(call if_qemu,$(GTEST_ARGS.qemu.$(QEMU_ARCH)),$(GTEST_ARGS.host.$(HOST_ARCH)))
+
+define TEST_run
+ @$(ECHO) -n "TEST $(TARGET_OR_MEMBER) "
+ @$(ECHO) "[$(COLOR_GREEN)RUN$(COLOR_RESET)]"
+ $(QUIET)(echo 1 > "$(OUT)$(TARGET_OR_MEMBER).status.test")
+ $(QUIET)(echo $(ROOT_CMD) SRC="$(SRC)" $(QEMU_CMD) $(VALGRIND_CMD) \
+ "$(strip $(call if_qemu, $(SYSROOT_OUT),$(OUT))$(TARGET_OR_MEMBER))" \
+ $(if $(filter-out 0,$(words $(GTEST_ARGS.real))),$(GTEST_ARGS.real),\
+ $(GTEST_ARGS)) >> "$(OUT)$(TARGET_OR_MEMBER).setup.test")
+ -$(QUIET)$(call if_qemu,$(SUDO_CMD) $(UNSHARE_CMD) -m) $(SHELL) \
+ $(OUT)$(TARGET_OR_MEMBER).setup.test \
+ && echo 0 > "$(OUT)$(TARGET_OR_MEMBER).status.test"
+endef
+
+# Recursive list reversal so that we get RMDIR_ON_CLEAN in reverse order.
+define reverse
+$(if $(1),$(call reverse,$(wordlist 2,$(words $(1)),$(1)))) $(firstword $(1))
+endef
+
+clean: qemu_clean
+clean: CLEAN($(OUT)*.d) CLEAN($(OUT)*.o) CLEAN($(OUT)*.debug)
+clean: CLEAN($(OUT)*.test) CLEAN($(OUT)*.depends)
+clean: CLEAN($(OUT)*.gcno) CLEAN($(OUT)*.gcda) CLEAN($(OUT)*.gcov)
+clean: CLEAN($(OUT)lcov-coverage.info) CLEAN($(OUT)lcov-html)
+
+clean:
+ $(QUIET)# Always delete the containing directory last.
+ $(call silent_rmdir,$(OUT))
+
+FORCE: ;
+# Empty rule for use when no special targets are needed, like large_tests
+NONE:
+
+.PHONY: clean NONE valgrind NONE
+.DEFAULT_GOAL := all
+# Don't let make blow away "intermediates"
+.PRECIOUS: %.pic.o %.pie.o %.a %.pic.a %.pie.a %.test
+
+# Start accruing build info
+OUT_DIRS = $(OUT)
+LD_DIRS = $(OUT)
+SRC_DIRS = $(SRC)
+
+include $(wildcard $(OUT)*.d)
+SUBMODULE_DIRS = $(wildcard $(SRC)/*/module.mk)
+include $(SUBMODULE_DIRS)
+
+
+else ## In duplicate inclusions of common.mk
+
+# Get the current inclusion directory without a trailing slash
+MODULE := $(patsubst %/,%, \
+ $(dir $(lastword $(filter-out %common.mk,$(MAKEFILE_LIST)))))
+MODULE := $(subst $(SRC)/,,$(MODULE))
+MODULE_NAME := $(subst /,_,$(MODULE))
+#VPATH := $(MODULE):$(VPATH)
+
+
+# Depth first
+$(eval OUT_DIRS += $(OUT)$(MODULE))
+$(eval SRC_DIRS += $(OUT)$(MODULE))
+$(eval LD_DIRS := $(LD_DIRS):$(OUT)$(MODULE))
+
+# Add the defaults from this dir to rm_clean
+clean: CLEAN($(OUT)$(MODULE)/*.d) CLEAN($(OUT)$(MODULE)/*.o)
+clean: CLEAN($(OUT)$(MODULE)/*.debug) CLEAN($(OUT)$(MODULE)/*.test)
+clean: CLEAN($(OUT)$(MODULE)/*.depends)
+clean: CLEAN($(OUT)$(MODULE)/*.gcno) CLEAN($(OUT)$(MODULE)/*.gcda)
+clean: CLEAN($(OUT)$(MODULE)/*.gcov) CLEAN($(OUT)lcov-coverage.info)
+clean: CLEAN($(OUT)lcov-html)
+
+$(info + submodule: $(MODULE_NAME))
+# We must eval otherwise they may be dropped.
+MODULE_C_OBJECTS = $(patsubst $(SRC)/$(MODULE)/%.c,$(MODULE)/%.o,\
+ $(wildcard $(SRC)/$(MODULE)/*.c))
+$(eval $(MODULE_NAME)_C_OBJECTS ?= $(MODULE_C_OBJECTS))
+MODULE_CXX_OBJECTS = $(patsubst $(SRC)/$(MODULE)/%.cc,$(MODULE)/%.o,\
+ $(wildcard $(SRC)/$(MODULE)/*.cc))
+$(eval $(MODULE_NAME)_CXX_OBJECTS ?= $(MODULE_CXX_OBJECTS))
+
+# Note, $(MODULE) is implicit in the path to the %.c.
+# See $(C_OBJECTS) for more details.
+# Register rules for the module objects.
+$(eval $(call add_object_rules,$(MODULE_C_OBJECTS),CC,c,CFLAGS,$(SRC)/))
+$(eval $(call add_object_rules,$(MODULE_CXX_OBJECTS),CXX,cc,CXXFLAGS,$(SRC)/))
+
+# Continue recursive inclusion of module.mk files
+SUBMODULE_DIRS = $(wildcard $(SRC)/$(MODULE)/*/module.mk)
+include $(wildcard $(OUT)$(MODULE)/*.d)
+include $(SUBMODULE_DIRS)
+
+endif
+endif ## pass-to-subcall wrapper for relocating the call directory
diff --git a/chromium/third_party/minigbm/src/cros_gralloc/Makefile b/chromium/third_party/minigbm/src/cros_gralloc/Makefile
new file mode 100644
index 00000000000..17e884fb210
--- /dev/null
+++ b/chromium/third_party/minigbm/src/cros_gralloc/Makefile
@@ -0,0 +1,46 @@
+# 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.
+
+GRALLOC = gralloc.cros.so
+
+SRCS = $(wildcard *.cc)
+SRCS += $(wildcard ../*.c)
+
+SRCS += $(wildcard gralloc0/*.cc)
+
+SOURCES = $(filter-out ../gbm%, $(SRCS))
+PKG_CONFIG ?= pkg-config
+
+VPATH = $(dir $(SOURCES))
+LIBDRM_CFLAGS := $(shell $(PKG_CONFIG) --cflags libdrm)
+LIBDRM_LIBS := $(shell $(PKG_CONFIG) --libs libdrm)
+
+CPPFLAGS += -Wall -fPIC -Werror -flto $(LIBDRM_CFLAGS)
+CXXFLAGS += -std=c++14
+CFLAGS += -std=c99
+LIBS += -shared -lcutils -lhardware -lsync $(LIBDRM_LIBS)
+
+OBJS = $(foreach source, $(SOURCES), $(addsuffix .o, $(basename $(source))))
+
+OBJECTS = $(addprefix $(TARGET_DIR), $(notdir $(OBJS)))
+LIBRARY = $(addprefix $(TARGET_DIR), $(GRALLOC))
+
+.PHONY: all clean
+
+all: $(LIBRARY)
+
+$(LIBRARY): $(OBJECTS)
+
+clean:
+ $(RM) $(LIBRARY)
+ $(RM) $(OBJECTS)
+
+$(LIBRARY):
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $^ -o $@ $(LIBS)
+
+$(TARGET_DIR)%.o: %.cc
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $^ -o $@ -MMD
+
+$(TARGET_DIR)%.o: %.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) -c $^ -o $@ -MMD
diff --git a/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_buffer.cc b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_buffer.cc
new file mode 100644
index 00000000000..b6da605515e
--- /dev/null
+++ b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_buffer.cc
@@ -0,0 +1,98 @@
+/*
+ * 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])
+{
+ void *vaddr = nullptr;
+
+ memset(addr, 0, DRV_MAX_PLANES * sizeof(*addr));
+
+ /*
+ * 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 -EINVAL;
+ }
+
+ if (flags) {
+ 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_),
+ BO_TRANSFER_READ_WRITE, &lock_data_[0], 0);
+ }
+
+ if (vaddr == MAP_FAILED) {
+ cros_gralloc_error("Mapping failed.");
+ return -EFAULT;
+ }
+ }
+
+ for (uint32_t plane = 0; plane < num_planes_; plane++)
+ addr[plane] = static_cast<uint8_t *>(vaddr) + drv_bo_get_plane_offset(bo_, plane);
+
+ lockcount_++;
+ return 0;
+}
+
+int32_t cros_gralloc_buffer::unlock()
+{
+ if (lockcount_ <= 0) {
+ cros_gralloc_error("Buffer was not locked.");
+ return -EINVAL;
+ }
+
+ if (!--lockcount_) {
+ if (lock_data_[0]) {
+ drv_bo_unmap(bo_, lock_data_[0]);
+ lock_data_[0] = nullptr;
+ }
+ }
+
+ return 0;
+}
diff --git a/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_buffer.h b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_buffer.h
new file mode 100644
index 00000000000..673ff9d8f0b
--- /dev/null
+++ b/chromium/third_party/minigbm/src/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/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_driver.cc b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_driver.cc
new file mode 100644
index 00000000000..f6e65b7bfb2
--- /dev/null
+++ b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_driver.cc
@@ -0,0 +1,316 @@
+/*
+ * 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 0;
+ }
+ }
+
+ return -ENODEV;
+}
+
+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->drv_usage);
+ combo = drv_get_combination(drv_, resolved_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;
+ uint32_t resolved_format;
+
+ struct bo *bo;
+ struct cros_gralloc_handle *hnd;
+
+ resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->drv_usage);
+ bo = drv_bo_create(drv_, descriptor->width, descriptor->height, resolved_format,
+ descriptor->drv_usage);
+ if (!bo) {
+ cros_gralloc_error("Failed to create bo.");
+ return -ENOMEM;
+ }
+
+ /*
+ * 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 -EINVAL;
+ }
+
+ 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->flags[0] = static_cast<uint32_t>(descriptor->drv_usage >> 32);
+ hnd->flags[1] = static_cast<uint32_t>(descriptor->drv_usage);
+ 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 0;
+}
+
+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 -EINVAL;
+ }
+
+ auto buffer = get_buffer(hnd);
+ if (buffer) {
+ handles_[hnd].second++;
+ buffer->increase_refcount();
+ return 0;
+ }
+
+ if (drmPrimeFDToHandle(drv_get_fd(drv_), hnd->fds[0], &id)) {
+ cros_gralloc_error("drmPrimeFDToHandle failed.");
+ return -errno;
+ }
+
+ 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;
+ data.flags = static_cast<uint64_t>(hnd->flags[0]) << 32;
+ data.flags |= hnd->flags[1];
+
+ 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 -EFAULT;
+
+ 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 0;
+}
+
+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 -EINVAL;
+ }
+
+ auto buffer = get_buffer(hnd);
+ if (!buffer) {
+ cros_gralloc_error("Invalid Reference.");
+ return -EINVAL;
+ }
+
+ if (!--handles_[hnd].second)
+ handles_.erase(hnd);
+
+ if (buffer->decrease_refcount() == 0) {
+ buffers_.erase(buffer->get_id());
+ delete buffer;
+ }
+
+ return 0;
+}
+
+int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence, uint64_t flags,
+ uint8_t *addr[DRV_MAX_PLANES])
+{
+ int32_t ret = cros_gralloc_sync_wait(acquire_fence);
+ if (ret)
+ return ret;
+
+ std::lock_guard<std::mutex> lock(mutex_);
+ auto hnd = cros_gralloc_convert_handle(handle);
+ if (!hnd) {
+ cros_gralloc_error("Invalid handle.");
+ return -EINVAL;
+ }
+
+ auto buffer = get_buffer(hnd);
+ if (!buffer) {
+ cros_gralloc_error("Invalid Reference.");
+ return -EINVAL;
+ }
+
+ return buffer->lock(flags, addr);
+}
+
+int32_t cros_gralloc_driver::unlock(buffer_handle_t handle, int32_t *release_fence)
+{
+ std::lock_guard<std::mutex> lock(mutex_);
+
+ auto hnd = cros_gralloc_convert_handle(handle);
+ if (!hnd) {
+ cros_gralloc_error("Invalid handle.");
+ return -EINVAL;
+ }
+
+ auto buffer = get_buffer(hnd);
+ if (!buffer) {
+ cros_gralloc_error("Invalid Reference.");
+ return -EINVAL;
+ }
+
+ /*
+ * From the ANativeWindow::dequeueBuffer documentation:
+ *
+ * "A value of -1 indicates that the caller may access the buffer immediately without
+ * waiting on a fence."
+ */
+ *release_fence = -1;
+ 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 -EINVAL;
+ }
+
+ auto buffer = get_buffer(hnd);
+ if (!buffer) {
+ cros_gralloc_error("Invalid Reference.");
+ return -EINVAL;
+ }
+
+ *out_store = static_cast<uint64_t>(buffer->get_id());
+ return 0;
+}
+
+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/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_driver.h b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_driver.h
new file mode 100644
index 00000000000..b8754977a40
--- /dev/null
+++ b/chromium/third_party/minigbm/src/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 *release_fence);
+
+ 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/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_handle.h b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_handle.h
new file mode 100644
index 00000000000..4cb554dc04a
--- /dev/null
+++ b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_handle.h
@@ -0,0 +1,39 @@
+/*
+ * 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 CROS_GRALLOC_HANDLE_H
+#define CROS_GRALLOC_HANDLE_H
+
+#include <cstdint>
+#include <cutils/native_handle.h>
+
+#define DRV_MAX_PLANES 4
+
+/*
+ * Only use 32-bit integers in the handle. This guarantees that the handle is
+ * densely packed (i.e, the compiler does not insert any padding).
+ */
+
+struct cros_gralloc_handle {
+ native_handle_t base;
+ int32_t fds[DRV_MAX_PLANES];
+ uint32_t strides[DRV_MAX_PLANES];
+ uint32_t offsets[DRV_MAX_PLANES];
+ uint32_t sizes[DRV_MAX_PLANES];
+ uint32_t format_modifiers[2 * DRV_MAX_PLANES];
+ uint32_t width;
+ uint32_t height;
+ uint32_t format; /* DRM format */
+ uint32_t flags[2]; /* driver creation time flags */
+ uint32_t magic;
+ uint32_t pixel_stride;
+ int32_t droid_format;
+ int32_t usage; /* Android usage. */
+};
+
+typedef const struct cros_gralloc_handle *cros_gralloc_handle_t;
+
+#endif
diff --git a/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_helpers.cc b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_helpers.cc
new file mode 100644
index 00000000000..e662084bd9f
--- /dev/null
+++ b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_helpers.cc
@@ -0,0 +1,95 @@
+/*
+ * 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_helpers.h"
+
+#include <cstdlib>
+#include <cutils/log.h>
+#include <sync/sync.h>
+
+uint32_t cros_gralloc_convert_format(int format)
+{
+ /*
+ * Conversion from HAL to fourcc-based DRV formats based on
+ * platform_android.c in mesa.
+ */
+
+ 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_RGB_565:
+ return DRM_FORMAT_RGB565;
+ case HAL_PIXEL_FORMAT_RGB_888:
+ return DRM_FORMAT_RGB888;
+ 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;
+ /*
+ * 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 HAL_PIXEL_FORMAT_BLOB:
+ return DRM_FORMAT_R8;
+ }
+
+ return DRM_FORMAT_NONE;
+}
+
+cros_gralloc_handle_t cros_gralloc_convert_handle(buffer_handle_t handle)
+{
+ auto hnd = reinterpret_cast<cros_gralloc_handle_t>(handle);
+ if (!hnd || hnd->magic != cros_gralloc_magic)
+ return nullptr;
+
+ return hnd;
+}
+
+int32_t cros_gralloc_sync_wait(int32_t acquire_fence)
+{
+ if (acquire_fence < 0)
+ return 0;
+
+ /*
+ * Wait initially for 1000 ms, and then wait indefinitely. The SYNC_IOC_WAIT
+ * documentation states the caller waits indefinitely on the fence if timeout < 0.
+ */
+ int err = sync_wait(acquire_fence, 1000);
+ if (err < 0) {
+ cros_gralloc_error("Timed out on sync wait, err = %s", strerror(errno));
+ err = sync_wait(acquire_fence, -1);
+ if (err < 0) {
+ cros_gralloc_error("sync wait error = %s", strerror(errno));
+ return -errno;
+ }
+ }
+
+ err = close(acquire_fence);
+ if (err) {
+ cros_gralloc_error("Unable to close fence fd, err = %s", strerror(errno));
+ return -errno;
+ }
+
+ return 0;
+}
+
+void cros_gralloc_log(const char *prefix, const char *file, int line, const char *format, ...)
+{
+ char buf[50];
+ snprintf(buf, sizeof(buf), "[%s:%s(%d)]", prefix, basename(file), line);
+
+ va_list args;
+ va_start(args, format);
+ __android_log_vprint(ANDROID_LOG_ERROR, buf, format, args);
+ va_end(args);
+}
diff --git a/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_helpers.h b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_helpers.h
new file mode 100644
index 00000000000..cf90ec8cb1a
--- /dev/null
+++ b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_helpers.h
@@ -0,0 +1,35 @@
+/*
+ * 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 CROS_GRALLOC_HELPERS_H
+#define CROS_GRALLOC_HELPERS_H
+
+#include "../drv.h"
+#include "cros_gralloc_handle.h"
+#include "cros_gralloc_types.h"
+
+#include <system/graphics.h>
+#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));
+
+uint32_t cros_gralloc_convert_format(int32_t format);
+
+cros_gralloc_handle_t cros_gralloc_convert_handle(buffer_handle_t handle);
+
+int32_t cros_gralloc_sync_wait(int32_t acquire_fence);
+
+__attribute__((format(printf, 4, 5))) void cros_gralloc_log(const char *prefix, const char *file,
+ int line, const char *format, ...);
+
+#define cros_gralloc_error(...) \
+ do { \
+ cros_gralloc_log("CROS_GRALLOC_ERROR", __FILE__, __LINE__, __VA_ARGS__); \
+ } while (0)
+
+#endif
diff --git a/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_types.h b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_types.h
new file mode 100644
index 00000000000..2f6122e1324
--- /dev/null
+++ b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_types.h
@@ -0,0 +1,20 @@
+/*
+ * 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
+
+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/chromium/third_party/minigbm/src/cros_gralloc/gralloc0/gralloc0.cc b/chromium/third_party/minigbm/src/cros_gralloc/gralloc0/gralloc0.cc
new file mode 100644
index 00000000000..533f8cac099
--- /dev/null
+++ b/chromium/third_party/minigbm/src/cros_gralloc/gralloc0/gralloc0.cc
@@ -0,0 +1,398 @@
+/*
+ * 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;
+ bool initialized;
+ std::mutex initialization_mutex;
+};
+
+/* 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_CAMERA_WRITE;
+ if (flags & GRALLOC_USAGE_HW_CAMERA_READ)
+ usage |= BO_USE_CAMERA_READ;
+ if (flags & GRALLOC_USAGE_RENDERSCRIPT)
+ usage |= BO_USE_RENDERSCRIPT;
+
+ 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 -EINVAL;
+ }
+
+ ret = mod->driver->allocate(&descriptor, handle);
+ if (ret)
+ return ret;
+
+ auto hnd = cros_gralloc_convert_handle(*handle);
+ *stride = hnd->pixel_stride;
+
+ return 0;
+}
+
+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 0;
+}
+
+static int gralloc0_init(struct gralloc0_module *mod, bool initialize_alloc)
+{
+ std::lock_guard<std::mutex> lock(mod->initialization_mutex);
+
+ if (mod->initialized)
+ return 0;
+
+ mod->driver = std::make_unique<cros_gralloc_driver>();
+ if (mod->driver->init()) {
+ cros_gralloc_error("Failed to initialize driver.");
+ return -ENODEV;
+ }
+
+ if (initialize_alloc) {
+ mod->alloc = std::make_unique<alloc_device_t>();
+ mod->alloc->alloc = gralloc0_alloc;
+ mod->alloc->free = gralloc0_free;
+ mod->alloc->common.tag = HARDWARE_DEVICE_TAG;
+ mod->alloc->common.version = 0;
+ mod->alloc->common.module = (hw_module_t *)mod;
+ mod->alloc->common.close = gralloc0_close;
+ }
+
+ mod->initialized = true;
+ return 0;
+}
+
+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->initialized) {
+ *dev = &module->alloc->common;
+ return 0;
+ }
+
+ if (strcmp(name, GRALLOC_HARDWARE_GPU0)) {
+ cros_gralloc_error("Incorrect device name - %s.", name);
+ return -EINVAL;
+ }
+
+ if (gralloc0_init(module, true))
+ return -ENODEV;
+
+ *dev = &module->alloc->common;
+ return 0;
+}
+
+static int gralloc0_register_buffer(struct gralloc_module_t const *module, buffer_handle_t handle)
+{
+ auto mod = (struct gralloc0_module *)module;
+
+ if (!mod->initialized)
+ if (gralloc0_init(mod, false))
+ return -ENODEV;
+
+ 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)
+{
+ return module->lockAsync(module, handle, usage, l, t, w, h, vaddr, -1);
+}
+
+static int gralloc0_unlock(struct gralloc_module_t const *module, buffer_handle_t handle)
+{
+ int32_t fence_fd, ret;
+ auto mod = (struct gralloc0_module *)module;
+ ret = mod->driver->unlock(handle, &fence_fd);
+ if (ret)
+ return ret;
+
+ ret = cros_gralloc_sync_wait(fence_fd);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+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 -EINVAL;
+ }
+
+ va_start(args, op);
+
+ ret = 0;
+ handle = va_arg(args, buffer_handle_t);
+ auto hnd = cros_gralloc_convert_handle(handle);
+ if (!hnd) {
+ cros_gralloc_error("Invalid handle.");
+ return -EINVAL;
+ }
+
+ 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 = -EINVAL;
+ }
+
+ 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)
+{
+ return module->lockAsync_ycbcr(module, handle, usage, l, t, w, h, ycbcr, -1);
+}
+
+static int gralloc0_lock_async(struct gralloc_module_t const *module, buffer_handle_t handle,
+ int usage, int l, int t, int w, int h, void **vaddr, int fence_fd)
+{
+ int32_t ret;
+ 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 -EINVAL;
+ }
+
+ if (hnd->droid_format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ cros_gralloc_error("HAL_PIXEL_FORMAT_YCbCr_*_888 format not compatible.");
+ return -EINVAL;
+ }
+
+ flags = gralloc0_convert_flags(usage);
+ ret = mod->driver->lock(handle, fence_fd, flags, addr);
+ *vaddr = addr[0];
+ return ret;
+}
+
+static int gralloc0_unlock_async(struct gralloc_module_t const *module, buffer_handle_t handle,
+ int *fence_fd)
+{
+ auto mod = (struct gralloc0_module *)module;
+ return mod->driver->unlock(handle, fence_fd);
+}
+
+static int gralloc0_lock_async_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, int fence_fd)
+{
+ uint64_t flags;
+ int32_t 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 -EINVAL;
+ }
+
+ if ((hnd->droid_format != HAL_PIXEL_FORMAT_YCbCr_420_888) &&
+ (hnd->droid_format != HAL_PIXEL_FORMAT_YV12) &&
+ (hnd->droid_format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)) {
+ cros_gralloc_error("Non-YUV format not compatible.");
+ return -EINVAL;
+ }
+
+ flags = gralloc0_convert_flags(usage);
+ ret = mod->driver->lock(handle, fence_fd, flags, addr);
+ if (ret)
+ return ret;
+
+ 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:
+ module->unlock(module, handle);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+// clang-format off
+static struct hw_module_methods_t gralloc0_module_methods = { .open = gralloc0_open };
+// clang-format on
+
+struct gralloc0_module HAL_MODULE_INFO_SYM = {
+ .base =
+ {
+ .common =
+ {
+ .tag = HARDWARE_MODULE_TAG,
+ .module_api_version = GRALLOC_MODULE_API_VERSION_0_3,
+ .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,
+ .lockAsync = gralloc0_lock_async,
+ .unlockAsync = gralloc0_unlock_async,
+ .lockAsync_ycbcr = gralloc0_lock_async_ycbcr,
+ },
+
+ .alloc = nullptr,
+ .driver = nullptr,
+ .initialized = false,
+};
diff --git a/chromium/third_party/minigbm/src/drv.c b/chromium/third_party/minigbm/src/drv.c
new file mode 100644
index 00000000000..10a63485ea5
--- /dev/null
+++ b/chromium/third_party/minigbm/src/drv.c
@@ -0,0 +1,608 @@
+/*
+ * 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 <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <xf86drm.h>
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+#ifdef DRV_AMDGPU
+extern struct backend backend_amdgpu;
+#endif
+extern struct backend backend_cirrus;
+extern struct backend backend_evdi;
+#ifdef DRV_EXYNOS
+extern struct backend backend_exynos;
+#endif
+extern struct backend backend_gma500;
+#ifdef DRV_I915
+extern struct backend backend_i915;
+#endif
+#ifdef DRV_MARVELL
+extern struct backend backend_marvell;
+#endif
+#ifdef DRV_MEDIATEK
+extern struct backend backend_mediatek;
+#endif
+extern struct backend backend_nouveau;
+#ifdef DRV_RADEON
+extern struct backend backend_radeon;
+#endif
+#ifdef DRV_ROCKCHIP
+extern struct backend backend_rockchip;
+#endif
+#ifdef DRV_TEGRA
+extern struct backend backend_tegra;
+#endif
+extern struct backend backend_udl;
+#ifdef DRV_VC4
+extern struct backend backend_vc4;
+#endif
+extern struct backend backend_vgem;
+extern struct backend backend_virtio_gpu;
+
+static struct backend *drv_get_backend(int fd)
+{
+ drmVersionPtr drm_version;
+ unsigned int i;
+
+ drm_version = drmGetVersion(fd);
+
+ if (!drm_version)
+ return NULL;
+
+ struct backend *backend_list[] = {
+#ifdef DRV_AMDGPU
+ &backend_amdgpu,
+#endif
+ &backend_cirrus, &backend_evdi,
+#ifdef DRV_EXYNOS
+ &backend_exynos,
+#endif
+ &backend_gma500,
+#ifdef DRV_I915
+ &backend_i915,
+#endif
+#ifdef DRV_MARVELL
+ &backend_marvell,
+#endif
+#ifdef DRV_MEDIATEK
+ &backend_mediatek,
+#endif
+ &backend_nouveau,
+#ifdef DRV_RADEON
+ &backend_radeon,
+#endif
+#ifdef DRV_ROCKCHIP
+ &backend_rockchip,
+#endif
+#ifdef DRV_TEGRA
+ &backend_tegra,
+#endif
+ &backend_udl,
+#ifdef DRV_VC4
+ &backend_vc4,
+#endif
+ &backend_vgem, &backend_virtio_gpu,
+ };
+
+ for (i = 0; i < ARRAY_SIZE(backend_list); i++)
+ if (!strcmp(drm_version->name, backend_list[i]->name)) {
+ drmFreeVersion(drm_version);
+ return backend_list[i];
+ }
+
+ drmFreeVersion(drm_version);
+ return NULL;
+}
+
+struct driver *drv_create(int fd)
+{
+ struct driver *drv;
+ int ret;
+
+ drv = (struct driver *)calloc(1, sizeof(*drv));
+
+ if (!drv)
+ return NULL;
+
+ drv->fd = fd;
+ drv->backend = drv_get_backend(fd);
+
+ if (!drv->backend)
+ goto free_driver;
+
+ if (pthread_mutex_init(&drv->driver_lock, NULL))
+ goto free_driver;
+
+ drv->buffer_table = drmHashCreate();
+ if (!drv->buffer_table)
+ goto free_lock;
+
+ drv->map_table = drmHashCreate();
+ if (!drv->map_table)
+ goto free_buffer_table;
+
+ /* Start with a power of 2 number of allocations. */
+ drv->backend->combos.allocations = 2;
+ drv->backend->combos.size = 0;
+ drv->backend->combos.data =
+ calloc(drv->backend->combos.allocations, sizeof(struct combination));
+ if (!drv->backend->combos.data)
+ goto free_map_table;
+
+ if (drv->backend->init) {
+ ret = drv->backend->init(drv);
+ if (ret) {
+ free(drv->backend->combos.data);
+ goto free_map_table;
+ }
+ }
+
+ return drv;
+
+free_map_table:
+ drmHashDestroy(drv->map_table);
+free_buffer_table:
+ drmHashDestroy(drv->buffer_table);
+free_lock:
+ pthread_mutex_destroy(&drv->driver_lock);
+free_driver:
+ free(drv);
+ return NULL;
+}
+
+void drv_destroy(struct driver *drv)
+{
+ pthread_mutex_lock(&drv->driver_lock);
+
+ if (drv->backend->close)
+ drv->backend->close(drv);
+
+ drmHashDestroy(drv->buffer_table);
+ drmHashDestroy(drv->map_table);
+
+ free(drv->backend->combos.data);
+
+ pthread_mutex_unlock(&drv->driver_lock);
+ pthread_mutex_destroy(&drv->driver_lock);
+
+ free(drv);
+}
+
+int drv_get_fd(struct driver *drv)
+{
+ return drv->fd;
+}
+
+const char *drv_get_name(struct driver *drv)
+{
+ return drv->backend->name;
+}
+
+struct combination *drv_get_combination(struct driver *drv, uint32_t format, uint64_t usage)
+{
+ struct combination *curr, *best;
+
+ if (format == DRM_FORMAT_NONE || usage == BO_USE_NONE)
+ return 0;
+
+ best = NULL;
+ uint32_t i;
+ for (i = 0; i < drv->backend->combos.size; i++) {
+ curr = &drv->backend->combos.data[i];
+ if ((format == curr->format) && usage == (curr->usage & usage))
+ if (!best || best->metadata.priority < curr->metadata.priority)
+ best = curr;
+ }
+
+ return best;
+}
+
+struct bo *drv_bo_new(struct driver *drv, uint32_t width, uint32_t height, uint32_t format,
+ uint64_t flags)
+{
+
+ struct bo *bo;
+ bo = (struct bo *)calloc(1, sizeof(*bo));
+
+ if (!bo)
+ return NULL;
+
+ bo->drv = drv;
+ bo->width = width;
+ bo->height = height;
+ bo->format = format;
+ bo->flags = flags;
+ bo->num_planes = drv_num_planes_from_format(format);
+
+ if (!bo->num_planes) {
+ free(bo);
+ return NULL;
+ }
+
+ return bo;
+}
+
+struct bo *drv_bo_create(struct driver *drv, uint32_t width, uint32_t height, uint32_t format,
+ uint64_t flags)
+{
+ int ret;
+ size_t plane;
+ struct bo *bo;
+
+ bo = drv_bo_new(drv, width, height, format, flags);
+
+ if (!bo)
+ return NULL;
+
+ ret = drv->backend->bo_create(bo, width, height, format, flags);
+
+ if (ret) {
+ free(bo);
+ return NULL;
+ }
+
+ pthread_mutex_lock(&drv->driver_lock);
+
+ for (plane = 0; plane < bo->num_planes; plane++)
+ drv_increment_reference_count(drv, bo, plane);
+
+ pthread_mutex_unlock(&drv->driver_lock);
+
+ return bo;
+}
+
+struct bo *drv_bo_create_with_modifiers(struct driver *drv, uint32_t width, uint32_t height,
+ 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) {
+ errno = ENOENT;
+ return NULL;
+ }
+
+ bo = drv_bo_new(drv, width, height, format, BO_USE_NONE);
+
+ if (!bo)
+ return NULL;
+
+ ret = drv->backend->bo_create_with_modifiers(bo, width, height, format, modifiers, count);
+
+ if (ret) {
+ free(bo);
+ return NULL;
+ }
+
+ pthread_mutex_lock(&drv->driver_lock);
+
+ for (plane = 0; plane < bo->num_planes; plane++)
+ drv_increment_reference_count(drv, bo, plane);
+
+ pthread_mutex_unlock(&drv->driver_lock);
+
+ return bo;
+}
+
+void drv_bo_destroy(struct bo *bo)
+{
+ size_t plane;
+ uintptr_t total = 0;
+ size_t map_count = 0;
+ struct driver *drv = bo->drv;
+
+ pthread_mutex_lock(&drv->driver_lock);
+
+ for (plane = 0; plane < bo->num_planes; plane++)
+ drv_decrement_reference_count(drv, bo, plane);
+
+ for (plane = 0; plane < bo->num_planes; plane++) {
+ void *ptr;
+
+ total += drv_get_reference_count(drv, bo, plane);
+ map_count += !drmHashLookup(bo->drv->map_table, bo->handles[plane].u32, &ptr);
+ }
+
+ pthread_mutex_unlock(&drv->driver_lock);
+
+ if (total == 0) {
+ /*
+ * If we leak a reference to the GEM handle being freed here in the mapping table,
+ * we risk using the mapping table entry later for a completely different BO that
+ * gets the same handle. (See b/38250067.)
+ */
+ assert(!map_count);
+ bo->drv->backend->bo_destroy(bo);
+ }
+
+ free(bo);
+}
+
+struct bo *drv_bo_import(struct driver *drv, struct drv_import_fd_data *data)
+{
+ int ret;
+ size_t plane;
+ struct bo *bo;
+
+ bo = drv_bo_new(drv, data->width, data->height, data->format, data->flags);
+
+ if (!bo)
+ return NULL;
+
+ ret = drv->backend->bo_import(bo, data);
+ if (ret) {
+ free(bo);
+ return NULL;
+ }
+
+ for (plane = 0; plane < bo->num_planes; plane++) {
+ bo->strides[plane] = data->strides[plane];
+ bo->offsets[plane] = data->offsets[plane];
+ bo->sizes[plane] = data->sizes[plane];
+ bo->format_modifiers[plane] = data->format_modifiers[plane];
+ bo->total_size += data->sizes[plane];
+ }
+
+ return bo;
+}
+
+void *drv_bo_map(struct bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height,
+ uint32_t flags, struct map_info **map_data, size_t plane)
+{
+ void *ptr;
+ uint8_t *addr;
+ size_t offset;
+ struct map_info *data;
+ int prot;
+
+ assert(width > 0);
+ assert(height > 0);
+ assert(x + width <= drv_bo_get_width(bo));
+ assert(y + height <= drv_bo_get_height(bo));
+ assert(BO_TRANSFER_READ_WRITE & flags);
+
+ pthread_mutex_lock(&bo->drv->driver_lock);
+
+ if (!drmHashLookup(bo->drv->map_table, bo->handles[plane].u32, &ptr)) {
+ data = (struct map_info *)ptr;
+ data->refcount++;
+ goto success;
+ }
+
+ data = calloc(1, sizeof(*data));
+ prot = BO_TRANSFER_WRITE & flags ? PROT_WRITE | PROT_READ : PROT_READ;
+ addr = bo->drv->backend->bo_map(bo, data, plane, prot);
+ if (addr == MAP_FAILED) {
+ *map_data = NULL;
+ free(data);
+ pthread_mutex_unlock(&bo->drv->driver_lock);
+ return MAP_FAILED;
+ }
+
+ data->refcount = 1;
+ data->addr = addr;
+ data->handle = bo->handles[plane].u32;
+ drmHashInsert(bo->drv->map_table, bo->handles[plane].u32, (void *)data);
+
+success:
+ *map_data = data;
+ offset = drv_bo_get_plane_stride(bo, plane) * y;
+ offset += drv_stride_from_format(bo->format, x, plane);
+ addr = (uint8_t *)data->addr;
+ addr += drv_bo_get_plane_offset(bo, plane) + offset;
+ pthread_mutex_unlock(&bo->drv->driver_lock);
+
+ return (void *)addr;
+}
+
+int drv_bo_unmap(struct bo *bo, struct map_info *data)
+{
+ int ret = 0;
+
+ assert(data);
+ assert(data->refcount >= 0);
+
+ pthread_mutex_lock(&bo->drv->driver_lock);
+
+ if (!--data->refcount) {
+ if (bo->drv->backend->bo_unmap)
+ ret = bo->drv->backend->bo_unmap(bo, data);
+ else
+ ret = munmap(data->addr, data->length);
+ drmHashDelete(bo->drv->map_table, data->handle);
+ free(data);
+ }
+
+ pthread_mutex_unlock(&bo->drv->driver_lock);
+
+ return ret;
+}
+
+uint32_t drv_bo_get_width(struct bo *bo)
+{
+ return bo->width;
+}
+
+uint32_t drv_bo_get_height(struct bo *bo)
+{
+ return bo->height;
+}
+
+uint32_t drv_bo_get_stride_or_tiling(struct bo *bo)
+{
+ return bo->tiling ? bo->tiling : drv_bo_get_plane_stride(bo, 0);
+}
+
+size_t drv_bo_get_num_planes(struct bo *bo)
+{
+ return bo->num_planes;
+}
+
+union bo_handle drv_bo_get_plane_handle(struct bo *bo, size_t plane)
+{
+ return bo->handles[plane];
+}
+
+#ifndef DRM_RDWR
+#define DRM_RDWR O_RDWR
+#endif
+
+int drv_bo_get_plane_fd(struct bo *bo, size_t plane)
+{
+
+ int ret, fd;
+ assert(plane < bo->num_planes);
+
+ ret = drmPrimeHandleToFD(bo->drv->fd, bo->handles[plane].u32, DRM_CLOEXEC | DRM_RDWR, &fd);
+
+ return (ret) ? ret : fd;
+}
+
+uint32_t drv_bo_get_plane_offset(struct bo *bo, size_t plane)
+{
+ assert(plane < bo->num_planes);
+ return bo->offsets[plane];
+}
+
+uint32_t drv_bo_get_plane_size(struct bo *bo, size_t plane)
+{
+ assert(plane < bo->num_planes);
+ return bo->sizes[plane];
+}
+
+uint32_t drv_bo_get_plane_stride(struct bo *bo, size_t plane)
+{
+ assert(plane < bo->num_planes);
+ return bo->strides[plane];
+}
+
+uint64_t drv_bo_get_plane_format_modifier(struct bo *bo, size_t plane)
+{
+ assert(plane < bo->num_planes);
+ return bo->format_modifiers[plane];
+}
+
+uint32_t drv_bo_get_format(struct bo *bo)
+{
+ return bo->format;
+}
+
+uint32_t drv_resolve_format(struct driver *drv, uint32_t format, uint64_t usage)
+{
+ if (drv->backend->resolve_format)
+ return drv->backend->resolve_format(format, usage);
+
+ return format;
+}
+
+size_t drv_num_planes_from_format(uint32_t format)
+{
+ switch (format) {
+ case DRM_FORMAT_ABGR1555:
+ case DRM_FORMAT_ABGR2101010:
+ case DRM_FORMAT_ABGR4444:
+ case DRM_FORMAT_ABGR8888:
+ case DRM_FORMAT_ARGB1555:
+ case DRM_FORMAT_ARGB2101010:
+ case DRM_FORMAT_ARGB4444:
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_AYUV:
+ case DRM_FORMAT_BGR233:
+ case DRM_FORMAT_BGR565:
+ case DRM_FORMAT_BGR888:
+ case DRM_FORMAT_BGRA1010102:
+ case DRM_FORMAT_BGRA4444:
+ case DRM_FORMAT_BGRA5551:
+ case DRM_FORMAT_BGRA8888:
+ case DRM_FORMAT_BGRX1010102:
+ case DRM_FORMAT_BGRX4444:
+ case DRM_FORMAT_BGRX5551:
+ case DRM_FORMAT_BGRX8888:
+ case DRM_FORMAT_C8:
+ case DRM_FORMAT_GR88:
+ case DRM_FORMAT_R8:
+ case DRM_FORMAT_RG88:
+ case DRM_FORMAT_RGB332:
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_RGB888:
+ case DRM_FORMAT_RGBA1010102:
+ case DRM_FORMAT_RGBA4444:
+ case DRM_FORMAT_RGBA5551:
+ case DRM_FORMAT_RGBA8888:
+ case DRM_FORMAT_RGBX1010102:
+ case DRM_FORMAT_RGBX4444:
+ case DRM_FORMAT_RGBX5551:
+ case DRM_FORMAT_RGBX8888:
+ case DRM_FORMAT_UYVY:
+ case DRM_FORMAT_VYUY:
+ case DRM_FORMAT_XBGR1555:
+ case DRM_FORMAT_XBGR2101010:
+ case DRM_FORMAT_XBGR4444:
+ case DRM_FORMAT_XBGR8888:
+ case DRM_FORMAT_XRGB1555:
+ case DRM_FORMAT_XRGB2101010:
+ case DRM_FORMAT_XRGB4444:
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_YUYV:
+ case DRM_FORMAT_YVYU:
+ return 1;
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV21:
+ return 2;
+ case DRM_FORMAT_YVU420:
+ case DRM_FORMAT_YVU420_ANDROID:
+ return 3;
+ }
+
+ fprintf(stderr, "drv: UNKNOWN FORMAT %d\n", format);
+ return 0;
+}
+
+uint32_t drv_size_from_format(uint32_t format, uint32_t stride, uint32_t height, size_t plane)
+{
+ assert(plane < drv_num_planes_from_format(format));
+ uint32_t vertical_subsampling;
+
+ switch (format) {
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_YVU420:
+ case DRM_FORMAT_YVU420_ANDROID:
+ vertical_subsampling = (plane == 0) ? 1 : 2;
+ break;
+ default:
+ vertical_subsampling = 1;
+ }
+
+ return stride * DIV_ROUND_UP(height, vertical_subsampling);
+}
+
+uint32_t drv_num_buffers_per_bo(struct bo *bo)
+{
+ uint32_t count = 0;
+ size_t plane, p;
+
+ for (plane = 0; plane < bo->num_planes; plane++) {
+ for (p = 0; p < plane; p++)
+ if (bo->handles[p].u32 == bo->handles[plane].u32)
+ break;
+ if (p == plane)
+ count++;
+ }
+
+ return count;
+}
diff --git a/chromium/third_party/minigbm/src/drv.h b/chromium/third_party/minigbm/src/drv.h
new file mode 100644
index 00000000000..e4678a118e5
--- /dev/null
+++ b/chromium/third_party/minigbm/src/drv.h
@@ -0,0 +1,154 @@
+/*
+ * 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_H_
+#define DRV_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_fourcc.h>
+#include <stdint.h>
+
+#define DRV_MAX_PLANES 4
+
+// clang-format off
+/* Use flags */
+#define BO_USE_NONE 0
+#define BO_USE_SCANOUT (1ull << 0)
+#define BO_USE_CURSOR (1ull << 1)
+#define BO_USE_CURSOR_64X64 BO_USE_CURSOR
+#define BO_USE_RENDERING (1ull << 2)
+#define BO_USE_LINEAR (1ull << 3)
+#define BO_USE_SW_READ_NEVER (1ull << 4)
+#define BO_USE_SW_READ_RARELY (1ull << 5)
+#define BO_USE_SW_READ_OFTEN (1ull << 6)
+#define BO_USE_SW_WRITE_NEVER (1ull << 7)
+#define BO_USE_SW_WRITE_RARELY (1ull << 8)
+#define BO_USE_SW_WRITE_OFTEN (1ull << 9)
+#define BO_USE_EXTERNAL_DISP (1ull << 10)
+#define BO_USE_PROTECTED (1ull << 11)
+#define BO_USE_HW_VIDEO_ENCODER (1ull << 12)
+#define BO_USE_CAMERA_WRITE (1ull << 13)
+#define BO_USE_CAMERA_READ (1ull << 14)
+#define BO_USE_RENDERSCRIPT (1ull << 16)
+#define BO_USE_TEXTURE (1ull << 17)
+
+/* Read-Write permissions for drv_bo_map() flags */
+#define BO_TRANSFER_NONE 0
+#define BO_TRANSFER_READ (1 << 0)
+#define BO_TRANSFER_WRITE (1 << 1)
+#define BO_TRANSFER_READ_WRITE (BO_TRANSFER_READ | BO_TRANSFER_WRITE)
+
+/* This is our extension to <drm_fourcc.h>. We need to make sure we don't step
+ * on the namespace of already defined formats, which can be done by using invalid
+ * fourcc codes.
+ */
+
+#define DRM_FORMAT_NONE fourcc_code('0', '0', '0', '0')
+#define DRM_FORMAT_YVU420_ANDROID fourcc_code('9', '9', '9', '7')
+#define DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED fourcc_code('9', '9', '9', '8')
+#define DRM_FORMAT_FLEX_YCbCr_420_888 fourcc_code('9', '9', '9', '9')
+
+// clang-format on
+struct driver;
+struct bo;
+struct combination;
+
+union bo_handle {
+ void *ptr;
+ int32_t s32;
+ uint32_t u32;
+ int64_t s64;
+ uint64_t u64;
+};
+
+struct drv_import_fd_data {
+ int fds[DRV_MAX_PLANES];
+ uint32_t strides[DRV_MAX_PLANES];
+ uint32_t offsets[DRV_MAX_PLANES];
+ uint32_t sizes[DRV_MAX_PLANES];
+ uint64_t format_modifiers[DRV_MAX_PLANES];
+ uint32_t width;
+ uint32_t height;
+ uint32_t format;
+ uint64_t flags;
+};
+
+struct map_info {
+ void *addr;
+ size_t length;
+ uint32_t handle;
+ int32_t refcount;
+ void *priv;
+};
+
+struct driver *drv_create(int fd);
+
+void drv_destroy(struct driver *drv);
+
+int drv_get_fd(struct driver *drv);
+
+const char *drv_get_name(struct driver *drv);
+
+struct combination *drv_get_combination(struct driver *drv, uint32_t format, uint64_t usage);
+
+struct bo *drv_bo_new(struct driver *drv, uint32_t width, uint32_t height, uint32_t format,
+ uint64_t flags);
+
+struct bo *drv_bo_create(struct driver *drv, uint32_t width, uint32_t height, uint32_t format,
+ uint64_t flags);
+
+struct bo *drv_bo_create_with_modifiers(struct driver *drv, uint32_t width, uint32_t height,
+ uint32_t format, const uint64_t *modifiers, uint32_t count);
+
+void drv_bo_destroy(struct bo *bo);
+
+struct bo *drv_bo_import(struct driver *drv, struct drv_import_fd_data *data);
+
+void *drv_bo_map(struct bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height,
+ uint32_t flags, struct map_info **map_data, size_t plane);
+
+int drv_bo_unmap(struct bo *bo, struct map_info *map_data);
+
+uint32_t drv_bo_get_width(struct bo *bo);
+
+uint32_t drv_bo_get_height(struct bo *bo);
+
+uint32_t drv_bo_get_stride_or_tiling(struct bo *bo);
+
+size_t drv_bo_get_num_planes(struct bo *bo);
+
+union bo_handle drv_bo_get_plane_handle(struct bo *bo, size_t plane);
+
+int drv_bo_get_plane_fd(struct bo *bo, size_t plane);
+
+uint32_t drv_bo_get_plane_offset(struct bo *bo, size_t plane);
+
+uint32_t drv_bo_get_plane_size(struct bo *bo, size_t plane);
+
+uint32_t drv_bo_get_plane_stride(struct bo *bo, size_t plane);
+
+uint64_t drv_bo_get_plane_format_modifier(struct bo *bo, size_t plane);
+
+uint32_t drv_bo_get_format(struct bo *bo);
+
+uint32_t drv_bo_get_stride_in_pixels(struct bo *bo);
+
+uint32_t drv_resolve_format(struct driver *drv, uint32_t format, uint64_t usage);
+
+size_t drv_num_planes_from_format(uint32_t format);
+
+uint32_t drv_size_from_format(uint32_t format, uint32_t stride, uint32_t height, size_t plane);
+
+uint32_t drv_num_buffers_per_bo(struct bo *bo);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/chromium/third_party/minigbm/src/drv_priv.h b/chromium/third_party/minigbm/src/drv_priv.h
new file mode 100644
index 00000000000..5547b787e91
--- /dev/null
+++ b/chromium/third_party/minigbm/src/drv_priv.h
@@ -0,0 +1,95 @@
+/*
+ * 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_PRIV_H
+#define DRV_PRIV_H
+
+#include <pthread.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include "drv.h"
+
+struct bo {
+ struct driver *drv;
+ uint32_t width;
+ uint32_t height;
+ uint32_t format;
+ uint32_t tiling;
+ size_t num_planes;
+ union bo_handle handles[DRV_MAX_PLANES];
+ uint32_t offsets[DRV_MAX_PLANES];
+ uint32_t sizes[DRV_MAX_PLANES];
+ uint32_t strides[DRV_MAX_PLANES];
+ uint64_t format_modifiers[DRV_MAX_PLANES];
+ uint64_t flags;
+ size_t total_size;
+ void *priv;
+};
+
+struct driver {
+ int fd;
+ struct backend *backend;
+ void *priv;
+ void *buffer_table;
+ void *map_table;
+ pthread_mutex_t driver_lock;
+};
+
+struct kms_item {
+ uint32_t format;
+ uint64_t modifier;
+ uint64_t usage;
+};
+
+struct format_metadata {
+ uint32_t priority;
+ uint32_t tiling;
+ uint64_t modifier;
+};
+
+struct combination {
+ uint32_t format;
+ struct format_metadata metadata;
+ uint64_t usage;
+};
+
+struct combinations {
+ struct combination *data;
+ uint32_t size;
+ uint32_t allocations;
+};
+
+struct backend {
+ char *name;
+ int (*init)(struct driver *drv);
+ void (*close)(struct driver *drv);
+ int (*bo_create)(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+ uint32_t flags);
+ int (*bo_create_with_modifiers)(struct bo *bo, uint32_t width, uint32_t height,
+ uint32_t format, const uint64_t *modifiers, uint32_t count);
+ 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 map_info *data, size_t plane, int prot);
+ int (*bo_unmap)(struct bo *bo, struct map_info *data);
+ uint32_t (*resolve_format)(uint32_t format, uint64_t usage);
+ struct combinations combos;
+};
+
+// clang-format off
+#define BO_USE_RENDER_MASK BO_USE_LINEAR | BO_USE_RENDERING | BO_USE_RENDERSCRIPT | \
+ BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN | BO_USE_SW_READ_RARELY | \
+ BO_USE_SW_WRITE_RARELY | BO_USE_TEXTURE
+
+#define BO_USE_TEXTURE_MASK BO_USE_LINEAR | BO_USE_RENDERSCRIPT | BO_USE_SW_READ_OFTEN | \
+ BO_USE_SW_WRITE_OFTEN | BO_USE_SW_READ_RARELY | \
+ BO_USE_SW_WRITE_RARELY | BO_USE_TEXTURE
+
+#define LINEAR_METADATA (struct format_metadata) { 0, 1, DRM_FORMAT_MOD_NONE }
+// clang-format on
+
+#endif
diff --git a/chromium/third_party/minigbm/src/evdi.c b/chromium/third_party/minigbm/src/evdi.c
new file mode 100644
index 00000000000..f66fb2d48bb
--- /dev/null
+++ b/chromium/third_party/minigbm/src/evdi.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2016 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 };
+
+static int evdi_init(struct driver *drv)
+{
+ int ret;
+ ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+ &LINEAR_METADATA, BO_USE_RENDER_MASK);
+ if (ret)
+ return ret;
+
+ return drv_modify_linear_combinations(drv);
+}
+
+struct backend backend_evdi = {
+ .name = "evdi",
+ .init = evdi_init,
+ .bo_create = drv_dumb_bo_create,
+ .bo_destroy = drv_dumb_bo_destroy,
+ .bo_import = drv_prime_bo_import,
+ .bo_map = drv_dumb_bo_map,
+};
diff --git a/chromium/third_party/minigbm/src/exynos.c b/chromium/third_party/minigbm/src/exynos.c
new file mode 100644
index 00000000000..0d935ebf13c
--- /dev/null
+++ b/chromium/third_party/minigbm/src/exynos.c
@@ -0,0 +1,117 @@
+/*
+ * 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)
+{
+ int ret;
+ ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+ &LINEAR_METADATA, BO_USE_RENDER_MASK);
+ if (ret)
+ return ret;
+
+ ret = drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats),
+ &LINEAR_METADATA, BO_USE_TEXTURE_MASK);
+ if (ret)
+ return ret;
+
+ return drv_modify_linear_combinations(drv);
+}
+
+static int exynos_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+ uint32_t 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->strides[0] = bo->strides[1] = width;
+ /* MFC v8+ requires 64 byte padding in the end of luma and chroma buffers. */
+ bo->sizes[0] = bo->strides[0] * height + 64;
+ bo->sizes[1] = bo->strides[1] * chroma_height + 64;
+ bo->offsets[0] = bo->offsets[1] = 0;
+ bo->total_size = bo->sizes[0] + bo->sizes[1];
+ } else if (format == DRM_FORMAT_XRGB8888 || format == DRM_FORMAT_ARGB8888) {
+ bo->strides[0] = drv_stride_from_format(format, width, 0);
+ bo->total_size = bo->sizes[0] = height * bo->strides[0];
+ bo->offsets[0] = 0;
+ } else {
+ fprintf(stderr, "drv: unsupported format %X\n", format);
+ assert(0);
+ return -EINVAL;
+ }
+
+ int ret;
+ for (plane = 0; plane < bo->num_planes; plane++) {
+ size_t size = bo->sizes[plane];
+ struct drm_exynos_gem_create gem_create;
+
+ memset(&gem_create, 0, sizeof(gem_create));
+ gem_create.size = size;
+ gem_create.flags = EXYNOS_BO_NONCONTIG;
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_EXYNOS_GEM_CREATE, &gem_create);
+ if (ret) {
+ fprintf(stderr, "drv: DRM_IOCTL_EXYNOS_GEM_CREATE failed (size=%zu)\n",
+ size);
+ goto cleanup_planes;
+ }
+
+ bo->handles[plane].u32 = gem_create.handle;
+ }
+
+ return 0;
+
+cleanup_planes:
+ for (; plane != 0; plane--) {
+ struct drm_gem_close gem_close;
+ memset(&gem_close, 0, sizeof(gem_close));
+ gem_close.handle = bo->handles[plane - 1].u32;
+ int gem_close_ret = drmIoctl(bo->drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
+ if (gem_close_ret) {
+ fprintf(stderr, "drv: 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
+ */
+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,
+};
+
+#endif
diff --git a/chromium/third_party/minigbm/src/gbm.c b/chromium/third_party/minigbm/src/gbm.c
new file mode 100644
index 00000000000..37fb1d914c7
--- /dev/null
+++ b/chromium/third_party/minigbm/src/gbm.c
@@ -0,0 +1,338 @@
+/*
+ * Copyright 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <assert.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <xf86drm.h>
+
+#include "drv.h"
+#include "gbm_helpers.h"
+#include "gbm_priv.h"
+#include "util.h"
+
+PUBLIC int gbm_device_get_fd(struct gbm_device *gbm)
+{
+
+ return drv_get_fd(gbm->drv);
+}
+
+PUBLIC const char *gbm_device_get_backend_name(struct gbm_device *gbm)
+{
+ return drv_get_name(gbm->drv);
+}
+
+PUBLIC int gbm_device_is_format_supported(struct gbm_device *gbm, uint32_t format, uint32_t usage)
+{
+ uint64_t drv_usage;
+
+ if (usage & GBM_BO_USE_CURSOR && usage & GBM_BO_USE_RENDERING)
+ return 0;
+
+ drv_usage = gbm_convert_flags(usage);
+
+ return (drv_get_combination(gbm->drv, format, drv_usage) != NULL);
+}
+
+PUBLIC struct gbm_device *gbm_create_device(int fd)
+{
+ struct gbm_device *gbm;
+
+ gbm = (struct gbm_device *)malloc(sizeof(*gbm));
+
+ if (!gbm)
+ return NULL;
+
+ gbm->drv = drv_create(fd);
+ if (!gbm->drv) {
+ free(gbm);
+ return NULL;
+ }
+
+ return gbm;
+}
+
+PUBLIC void gbm_device_destroy(struct gbm_device *gbm)
+{
+ drv_destroy(gbm->drv);
+ free(gbm);
+}
+
+PUBLIC struct gbm_surface *gbm_surface_create(struct gbm_device *gbm, uint32_t width,
+ uint32_t height, uint32_t format, uint32_t flags)
+{
+ struct gbm_surface *surface = (struct gbm_surface *)malloc(sizeof(*surface));
+
+ if (!surface)
+ return NULL;
+
+ return surface;
+}
+
+PUBLIC void gbm_surface_destroy(struct gbm_surface *surface)
+{
+ free(surface);
+}
+
+PUBLIC struct gbm_bo *gbm_surface_lock_front_buffer(struct gbm_surface *surface)
+{
+ return NULL;
+}
+
+PUBLIC void gbm_surface_release_buffer(struct gbm_surface *surface, struct gbm_bo *bo)
+{
+}
+
+static struct gbm_bo *gbm_bo_new(struct gbm_device *gbm, uint32_t format)
+{
+ struct gbm_bo *bo;
+
+ bo = (struct gbm_bo *)calloc(1, sizeof(*bo));
+ if (!bo)
+ return NULL;
+
+ bo->gbm = gbm;
+ bo->gbm_format = format;
+
+ return bo;
+}
+
+PUBLIC struct gbm_bo *gbm_bo_create(struct gbm_device *gbm, uint32_t width, uint32_t height,
+ uint32_t format, uint32_t flags)
+{
+ struct gbm_bo *bo;
+
+ if (!gbm_device_is_format_supported(gbm, format, flags))
+ return NULL;
+
+ bo = gbm_bo_new(gbm, format);
+
+ if (!bo)
+ return NULL;
+
+ bo->bo = drv_bo_create(gbm->drv, width, height, format, gbm_convert_flags(flags));
+
+ if (!bo->bo) {
+ free(bo);
+ return NULL;
+ }
+
+ return bo;
+}
+
+PUBLIC struct gbm_bo *gbm_bo_create_with_modifiers(struct gbm_device *gbm, uint32_t width,
+ uint32_t height, uint32_t format,
+ const uint64_t *modifiers, uint32_t count)
+{
+ struct gbm_bo *bo;
+
+ bo = gbm_bo_new(gbm, format);
+
+ if (!bo)
+ return NULL;
+
+ bo->bo = drv_bo_create_with_modifiers(gbm->drv, width, height, format, modifiers, count);
+
+ if (!bo->bo) {
+ free(bo);
+ return NULL;
+ }
+
+ return bo;
+}
+
+PUBLIC void gbm_bo_destroy(struct gbm_bo *bo)
+{
+ if (bo->destroy_user_data) {
+ bo->destroy_user_data(bo, bo->user_data);
+ bo->destroy_user_data = NULL;
+ bo->user_data = NULL;
+ }
+
+ drv_bo_destroy(bo->bo);
+ free(bo);
+}
+
+PUBLIC struct gbm_bo *gbm_bo_import(struct gbm_device *gbm, uint32_t type, void *buffer,
+ uint32_t usage)
+{
+ struct gbm_bo *bo;
+ struct drv_import_fd_data drv_data;
+ struct gbm_import_fd_data *fd_data = buffer;
+ struct gbm_import_fd_planar_data *fd_planar_data = buffer;
+ uint32_t gbm_format;
+ size_t num_planes, i;
+
+ memset(&drv_data, 0, sizeof(drv_data));
+
+ switch (type) {
+ case GBM_BO_IMPORT_FD:
+ gbm_format = fd_data->format;
+ drv_data.width = fd_data->width;
+ drv_data.height = fd_data->height;
+ drv_data.format = fd_data->format;
+ drv_data.fds[0] = fd_data->fd;
+ drv_data.strides[0] = fd_data->stride;
+ drv_data.sizes[0] = fd_data->height * fd_data->stride;
+ break;
+ case GBM_BO_IMPORT_FD_PLANAR:
+ gbm_format = fd_planar_data->format;
+ drv_data.width = fd_planar_data->width;
+ drv_data.height = fd_planar_data->height;
+ drv_data.format = fd_planar_data->format;
+ num_planes = drv_num_planes_from_format(drv_data.format);
+
+ assert(num_planes);
+
+ for (i = 0; i < num_planes; i++) {
+ drv_data.fds[i] = fd_planar_data->fds[i];
+ drv_data.offsets[i] = fd_planar_data->offsets[i];
+ drv_data.strides[i] = fd_planar_data->strides[i];
+ drv_data.format_modifiers[i] = fd_planar_data->format_modifiers[i];
+
+ drv_data.sizes[i] = drv_size_from_format(
+ drv_data.format, drv_data.strides[i], drv_data.height, i);
+ }
+
+ for (i = num_planes; i < GBM_MAX_PLANES; i++)
+ drv_data.fds[i] = -1;
+
+ break;
+ default:
+ return NULL;
+ }
+
+ if (!gbm_device_is_format_supported(gbm, gbm_format, usage))
+ return NULL;
+
+ bo = gbm_bo_new(gbm, gbm_format);
+
+ if (!bo)
+ return NULL;
+
+ bo->bo = drv_bo_import(gbm->drv, &drv_data);
+
+ if (!bo->bo) {
+ free(bo);
+ return NULL;
+ }
+
+ return bo;
+}
+
+PUBLIC void *gbm_bo_map(struct gbm_bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height,
+ uint32_t flags, uint32_t *stride, void **map_data, size_t plane)
+{
+ if (!bo || width == 0 || height == 0 || !stride || !map_data)
+ return NULL;
+
+ *stride = gbm_bo_get_plane_stride(bo, plane);
+ uint32_t drv_flags = flags & GBM_BO_TRANSFER_READ ? BO_TRANSFER_READ : BO_TRANSFER_NONE;
+ drv_flags |= flags & GBM_BO_TRANSFER_WRITE ? BO_TRANSFER_WRITE : BO_TRANSFER_NONE;
+ return drv_bo_map(bo->bo, x, y, width, height, drv_flags, (struct map_info **)map_data,
+ plane);
+}
+
+PUBLIC void gbm_bo_unmap(struct gbm_bo *bo, void *map_data)
+{
+ assert(bo);
+ drv_bo_unmap(bo->bo, map_data);
+}
+
+PUBLIC uint32_t gbm_bo_get_width(struct gbm_bo *bo)
+{
+ return drv_bo_get_width(bo->bo);
+}
+
+PUBLIC uint32_t gbm_bo_get_height(struct gbm_bo *bo)
+{
+ return drv_bo_get_height(bo->bo);
+}
+
+PUBLIC uint32_t gbm_bo_get_stride(struct gbm_bo *bo)
+{
+ return gbm_bo_get_plane_stride(bo, 0);
+}
+
+PUBLIC uint32_t gbm_bo_get_stride_or_tiling(struct gbm_bo *bo)
+{
+ return drv_bo_get_stride_or_tiling(bo->bo);
+}
+
+PUBLIC uint32_t gbm_bo_get_format(struct gbm_bo *bo)
+{
+ return bo->gbm_format;
+}
+
+PUBLIC uint64_t gbm_bo_get_format_modifier(struct gbm_bo *bo)
+{
+ return gbm_bo_get_plane_format_modifier(bo, 0);
+}
+
+PUBLIC struct gbm_device *gbm_bo_get_device(struct gbm_bo *bo)
+{
+ return bo->gbm;
+}
+
+PUBLIC union gbm_bo_handle gbm_bo_get_handle(struct gbm_bo *bo)
+{
+ return gbm_bo_get_plane_handle(bo, 0);
+}
+
+PUBLIC int gbm_bo_get_fd(struct gbm_bo *bo)
+{
+ return gbm_bo_get_plane_fd(bo, 0);
+}
+
+PUBLIC size_t gbm_bo_get_num_planes(struct gbm_bo *bo)
+{
+ return drv_bo_get_num_planes(bo->bo);
+}
+
+PUBLIC union gbm_bo_handle gbm_bo_get_plane_handle(struct gbm_bo *bo, size_t plane)
+{
+ return (union gbm_bo_handle)drv_bo_get_plane_handle(bo->bo, plane).u64;
+}
+
+PUBLIC int gbm_bo_get_plane_fd(struct gbm_bo *bo, size_t plane)
+{
+ return drv_bo_get_plane_fd(bo->bo, plane);
+}
+
+PUBLIC uint32_t gbm_bo_get_plane_offset(struct gbm_bo *bo, size_t plane)
+{
+ return drv_bo_get_plane_offset(bo->bo, plane);
+}
+
+PUBLIC uint32_t gbm_bo_get_plane_size(struct gbm_bo *bo, size_t plane)
+{
+ return drv_bo_get_plane_size(bo->bo, plane);
+}
+
+PUBLIC uint32_t gbm_bo_get_plane_stride(struct gbm_bo *bo, size_t plane)
+{
+ return drv_bo_get_plane_stride(bo->bo, plane);
+}
+
+PUBLIC uint64_t gbm_bo_get_plane_format_modifier(struct gbm_bo *bo, size_t plane)
+{
+ return drv_bo_get_plane_format_modifier(bo->bo, plane);
+}
+
+PUBLIC void gbm_bo_set_user_data(struct gbm_bo *bo, void *data,
+ void (*destroy_user_data)(struct gbm_bo *, void *))
+{
+ bo->user_data = data;
+ bo->destroy_user_data = destroy_user_data;
+}
+
+PUBLIC void *gbm_bo_get_user_data(struct gbm_bo *bo)
+{
+ return bo->user_data;
+}
diff --git a/chromium/third_party/minigbm/src/gbm.h b/chromium/third_party/minigbm/src/gbm.h
new file mode 100644
index 00000000000..5ec13bc003d
--- /dev/null
+++ b/chromium/third_party/minigbm/src/gbm.h
@@ -0,0 +1,425 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Benjamin Franzke <benjaminfranzke@googlemail.com>
+ */
+
+#ifndef _GBM_H_
+#define _GBM_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define __GBM__ 1
+
+#include <stddef.h>
+#include <stdint.h>
+
+/**
+ * \file gbm.h
+ * \brief Generic Buffer Manager
+ */
+
+struct gbm_device;
+struct gbm_bo;
+struct gbm_surface;
+
+/**
+ * \mainpage The Generic Buffer Manager
+ *
+ * This module provides an abstraction that the caller can use to request a
+ * buffer from the underlying memory management system for the platform.
+ *
+ * This allows the creation of portable code whilst still allowing access to
+ * the underlying memory manager.
+ */
+
+/**
+ * Abstraction representing the handle to a buffer allocated by the
+ * manager
+ */
+union gbm_bo_handle {
+ void *ptr;
+ int32_t s32;
+ uint32_t u32;
+ int64_t s64;
+ uint64_t u64;
+};
+
+#define GBM_MAX_PLANES 4
+
+#define __gbm_fourcc_code(a,b,c,d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | \
+ ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
+
+#define GBM_FORMAT_BIG_ENDIAN (1<<31) /* format is big endian instead of little endian */
+
+/* color index */
+#define GBM_FORMAT_C8 __gbm_fourcc_code('C', '8', ' ', ' ') /* [7:0] C */
+
+/* 8 bpp Red */
+#define GBM_FORMAT_R8 __gbm_fourcc_code('R', '8', ' ', ' ') /* [7:0] R */
+
+/* 16 bpp RG */
+#define GBM_FORMAT_RG88 __gbm_fourcc_code('R', 'G', '8', '8') /* [15:0] R:G 8:8 little endian */
+#define GBM_FORMAT_GR88 __gbm_fourcc_code('G', 'R', '8', '8') /* [15:0] G:R 8:8 little endian */
+
+/* 8 bpp RGB */
+#define GBM_FORMAT_RGB332 __gbm_fourcc_code('R', 'G', 'B', '8') /* [7:0] R:G:B 3:3:2 */
+#define GBM_FORMAT_BGR233 __gbm_fourcc_code('B', 'G', 'R', '8') /* [7:0] B:G:R 2:3:3 */
+
+/* 16 bpp RGB */
+#define GBM_FORMAT_XRGB4444 __gbm_fourcc_code('X', 'R', '1', '2') /* [15:0] x:R:G:B 4:4:4:4 little endian */
+#define GBM_FORMAT_XBGR4444 __gbm_fourcc_code('X', 'B', '1', '2') /* [15:0] x:B:G:R 4:4:4:4 little endian */
+#define GBM_FORMAT_RGBX4444 __gbm_fourcc_code('R', 'X', '1', '2') /* [15:0] R:G:B:x 4:4:4:4 little endian */
+#define GBM_FORMAT_BGRX4444 __gbm_fourcc_code('B', 'X', '1', '2') /* [15:0] B:G:R:x 4:4:4:4 little endian */
+
+#define GBM_FORMAT_ARGB4444 __gbm_fourcc_code('A', 'R', '1', '2') /* [15:0] A:R:G:B 4:4:4:4 little endian */
+#define GBM_FORMAT_ABGR4444 __gbm_fourcc_code('A', 'B', '1', '2') /* [15:0] A:B:G:R 4:4:4:4 little endian */
+#define GBM_FORMAT_RGBA4444 __gbm_fourcc_code('R', 'A', '1', '2') /* [15:0] R:G:B:A 4:4:4:4 little endian */
+#define GBM_FORMAT_BGRA4444 __gbm_fourcc_code('B', 'A', '1', '2') /* [15:0] B:G:R:A 4:4:4:4 little endian */
+
+#define GBM_FORMAT_XRGB1555 __gbm_fourcc_code('X', 'R', '1', '5') /* [15:0] x:R:G:B 1:5:5:5 little endian */
+#define GBM_FORMAT_XBGR1555 __gbm_fourcc_code('X', 'B', '1', '5') /* [15:0] x:B:G:R 1:5:5:5 little endian */
+#define GBM_FORMAT_RGBX5551 __gbm_fourcc_code('R', 'X', '1', '5') /* [15:0] R:G:B:x 5:5:5:1 little endian */
+#define GBM_FORMAT_BGRX5551 __gbm_fourcc_code('B', 'X', '1', '5') /* [15:0] B:G:R:x 5:5:5:1 little endian */
+
+#define GBM_FORMAT_ARGB1555 __gbm_fourcc_code('A', 'R', '1', '5') /* [15:0] A:R:G:B 1:5:5:5 little endian */
+#define GBM_FORMAT_ABGR1555 __gbm_fourcc_code('A', 'B', '1', '5') /* [15:0] A:B:G:R 1:5:5:5 little endian */
+#define GBM_FORMAT_RGBA5551 __gbm_fourcc_code('R', 'A', '1', '5') /* [15:0] R:G:B:A 5:5:5:1 little endian */
+#define GBM_FORMAT_BGRA5551 __gbm_fourcc_code('B', 'A', '1', '5') /* [15:0] B:G:R:A 5:5:5:1 little endian */
+
+#define GBM_FORMAT_RGB565 __gbm_fourcc_code('R', 'G', '1', '6') /* [15:0] R:G:B 5:6:5 little endian */
+#define GBM_FORMAT_BGR565 __gbm_fourcc_code('B', 'G', '1', '6') /* [15:0] B:G:R 5:6:5 little endian */
+
+/* 24 bpp RGB */
+#define GBM_FORMAT_RGB888 __gbm_fourcc_code('R', 'G', '2', '4') /* [23:0] R:G:B little endian */
+#define GBM_FORMAT_BGR888 __gbm_fourcc_code('B', 'G', '2', '4') /* [23:0] B:G:R little endian */
+
+/* 32 bpp RGB */
+#define GBM_FORMAT_XRGB8888 __gbm_fourcc_code('X', 'R', '2', '4') /* [31:0] x:R:G:B 8:8:8:8 little endian */
+#define GBM_FORMAT_XBGR8888 __gbm_fourcc_code('X', 'B', '2', '4') /* [31:0] x:B:G:R 8:8:8:8 little endian */
+#define GBM_FORMAT_RGBX8888 __gbm_fourcc_code('R', 'X', '2', '4') /* [31:0] R:G:B:x 8:8:8:8 little endian */
+#define GBM_FORMAT_BGRX8888 __gbm_fourcc_code('B', 'X', '2', '4') /* [31:0] B:G:R:x 8:8:8:8 little endian */
+
+#define GBM_FORMAT_ARGB8888 __gbm_fourcc_code('A', 'R', '2', '4') /* [31:0] A:R:G:B 8:8:8:8 little endian */
+#define GBM_FORMAT_ABGR8888 __gbm_fourcc_code('A', 'B', '2', '4') /* [31:0] A:B:G:R 8:8:8:8 little endian */
+#define GBM_FORMAT_RGBA8888 __gbm_fourcc_code('R', 'A', '2', '4') /* [31:0] R:G:B:A 8:8:8:8 little endian */
+#define GBM_FORMAT_BGRA8888 __gbm_fourcc_code('B', 'A', '2', '4') /* [31:0] B:G:R:A 8:8:8:8 little endian */
+
+#define GBM_FORMAT_XRGB2101010 __gbm_fourcc_code('X', 'R', '3', '0') /* [31:0] x:R:G:B 2:10:10:10 little endian */
+#define GBM_FORMAT_XBGR2101010 __gbm_fourcc_code('X', 'B', '3', '0') /* [31:0] x:B:G:R 2:10:10:10 little endian */
+#define GBM_FORMAT_RGBX1010102 __gbm_fourcc_code('R', 'X', '3', '0') /* [31:0] R:G:B:x 10:10:10:2 little endian */
+#define GBM_FORMAT_BGRX1010102 __gbm_fourcc_code('B', 'X', '3', '0') /* [31:0] B:G:R:x 10:10:10:2 little endian */
+
+#define GBM_FORMAT_ARGB2101010 __gbm_fourcc_code('A', 'R', '3', '0') /* [31:0] A:R:G:B 2:10:10:10 little endian */
+#define GBM_FORMAT_ABGR2101010 __gbm_fourcc_code('A', 'B', '3', '0') /* [31:0] A:B:G:R 2:10:10:10 little endian */
+#define GBM_FORMAT_RGBA1010102 __gbm_fourcc_code('R', 'A', '3', '0') /* [31:0] R:G:B:A 10:10:10:2 little endian */
+#define GBM_FORMAT_BGRA1010102 __gbm_fourcc_code('B', 'A', '3', '0') /* [31:0] B:G:R:A 10:10:10:2 little endian */
+
+/* packed YCbCr */
+#define GBM_FORMAT_YUYV __gbm_fourcc_code('Y', 'U', 'Y', 'V') /* [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian */
+#define GBM_FORMAT_YVYU __gbm_fourcc_code('Y', 'V', 'Y', 'U') /* [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian */
+#define GBM_FORMAT_UYVY __gbm_fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */
+#define GBM_FORMAT_VYUY __gbm_fourcc_code('V', 'Y', 'U', 'Y') /* [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian */
+
+#define GBM_FORMAT_AYUV __gbm_fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */
+
+/*
+ * 2 plane YCbCr
+ * index 0 = Y plane, [7:0] Y
+ * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
+ * or
+ * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
+ */
+#define GBM_FORMAT_NV12 __gbm_fourcc_code('N', 'V', '1', '2') /* 2x2 subsampled Cr:Cb plane */
+#define GBM_FORMAT_NV21 __gbm_fourcc_code('N', 'V', '2', '1') /* 2x2 subsampled Cb:Cr plane */
+#define GBM_FORMAT_NV16 __gbm_fourcc_code('N', 'V', '1', '6') /* 2x1 subsampled Cr:Cb plane */
+#define GBM_FORMAT_NV61 __gbm_fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */
+
+/*
+ * 3 plane YCbCr
+ * index 0: Y plane, [7:0] Y
+ * index 1: Cb plane, [7:0] Cb
+ * index 2: Cr plane, [7:0] Cr
+ * or
+ * index 1: Cr plane, [7:0] Cr
+ * index 2: Cb plane, [7:0] Cb
+ */
+#define GBM_FORMAT_YUV410 __gbm_fourcc_code('Y', 'U', 'V', '9') /* 4x4 subsampled Cb (1) and Cr (2) planes */
+#define GBM_FORMAT_YVU410 __gbm_fourcc_code('Y', 'V', 'U', '9') /* 4x4 subsampled Cr (1) and Cb (2) planes */
+#define GBM_FORMAT_YUV411 __gbm_fourcc_code('Y', 'U', '1', '1') /* 4x1 subsampled Cb (1) and Cr (2) planes */
+#define GBM_FORMAT_YVU411 __gbm_fourcc_code('Y', 'V', '1', '1') /* 4x1 subsampled Cr (1) and Cb (2) planes */
+#define GBM_FORMAT_YUV420 __gbm_fourcc_code('Y', 'U', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes */
+#define GBM_FORMAT_YVU420 __gbm_fourcc_code('Y', 'V', '1', '2') /* 2x2 subsampled Cr (1) and Cb (2) planes */
+#define GBM_FORMAT_YUV422 __gbm_fourcc_code('Y', 'U', '1', '6') /* 2x1 subsampled Cb (1) and Cr (2) planes */
+#define GBM_FORMAT_YVU422 __gbm_fourcc_code('Y', 'V', '1', '6') /* 2x1 subsampled Cr (1) and Cb (2) planes */
+#define GBM_FORMAT_YUV444 __gbm_fourcc_code('Y', 'U', '2', '4') /* non-subsampled Cb (1) and Cr (2) planes */
+#define GBM_FORMAT_YVU444 __gbm_fourcc_code('Y', 'V', '2', '4') /* non-subsampled Cr (1) and Cb (2) planes */
+
+/*
+ * Format Modifiers:
+ *
+ * Format modifiers describe, typically, a re-ordering or modification
+ * of the data in a plane of an FB. This can be used to express tiled/
+ * swizzled formats, or compression, or a combination of the two.
+ *
+ * The upper 8 bits of the format modifier are a vendor-id as assigned
+ * below. The lower 56 bits are assigned as vendor sees fit.
+ */
+
+/* Vendor Ids: */
+#define GBM_FORMAT_MOD_NONE 0
+#define GBM_FORMAT_MOD_VENDOR_INTEL 0x01
+#define GBM_FORMAT_MOD_VENDOR_AMD 0x02
+#define GBM_FORMAT_MOD_VENDOR_NV 0x03
+#define GBM_FORMAT_MOD_VENDOR_SAMSUNG 0x04
+#define GBM_FORMAT_MOD_VENDOR_QCOM 0x05
+/* add more to the end as needed */
+
+#define gbm_fourcc_mod_code(vendor, val) \
+ ((((__u64)GBM_FORMAT_MOD_VENDOR_## vendor) << 56) | (val & 0x00ffffffffffffffULL))
+
+/**
+ * Flags to indicate the intended use for the buffer - these are passed into
+ * gbm_bo_create(). The caller must set the union of all the flags that are
+ * appropriate
+ *
+ * \sa Use gbm_device_is_format_supported() to check if the combination of format
+ * and use flags are supported
+ */
+enum gbm_bo_flags {
+ /**
+ * Buffer is going to be presented to the screen using an API such as KMS
+ */
+ GBM_BO_USE_SCANOUT = (1 << 0),
+ /**
+ * Buffer is going to be used as cursor
+ */
+ GBM_BO_USE_CURSOR = (1 << 1),
+ /**
+ * Deprecated
+ */
+ GBM_BO_USE_CURSOR_64X64 = GBM_BO_USE_CURSOR,
+ /**
+ * Buffer is to be used for rendering - for example it is going to be used
+ * as the storage for a color buffer
+ */
+ GBM_BO_USE_RENDERING = (1 << 2),
+ /**
+ * Deprecated
+ */
+ GBM_BO_USE_WRITE = (1 << 3),
+ /**
+ * Buffer is guaranteed to be laid out linearly in memory. That is, the
+ * buffer is laid out as an array with 'height' blocks, each block with
+ * length 'stride'. Each stride is in the same order as the rows of the
+ * buffer.
+ */
+ GBM_BO_USE_LINEAR = (1 << 4),
+ /**
+ * The buffer will be used as a texture that will be sampled from.
+ */
+ GBM_BO_USE_TEXTURING = (1 << 5),
+ /**
+ * The buffer will be written to by a camera subsystem.
+ */
+ GBM_BO_USE_CAMERA_WRITE = (1 << 6),
+ /**
+ * The buffer will be read from by a camera subsystem.
+ */
+ GBM_BO_USE_CAMERA_READ = (1 << 7),
+};
+
+int
+gbm_device_get_fd(struct gbm_device *gbm);
+
+const char *
+gbm_device_get_backend_name(struct gbm_device *gbm);
+
+int
+gbm_device_is_format_supported(struct gbm_device *gbm,
+ uint32_t format, uint32_t usage);
+
+void
+gbm_device_destroy(struct gbm_device *gbm);
+
+struct gbm_device *
+gbm_create_device(int fd);
+
+struct gbm_bo *
+gbm_bo_create(struct gbm_device *gbm,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t flags);
+
+struct gbm_bo *
+gbm_bo_create_with_modifiers(struct gbm_device *gbm,
+ uint32_t width, uint32_t height,
+ uint32_t format,
+ const uint64_t *modifiers, uint32_t count);
+
+#define GBM_BO_IMPORT_WL_BUFFER 0x5501
+#define GBM_BO_IMPORT_EGL_IMAGE 0x5502
+#define GBM_BO_IMPORT_FD 0x5503
+#define GBM_BO_IMPORT_FD_PLANAR 0x5504
+
+struct gbm_import_fd_data {
+ int fd;
+ uint32_t width;
+ uint32_t height;
+ uint32_t stride;
+ uint32_t format;
+};
+
+struct gbm_import_fd_planar_data {
+ int fds[GBM_MAX_PLANES];
+ uint32_t width;
+ uint32_t height;
+ uint32_t format;
+ uint32_t strides[GBM_MAX_PLANES];
+ uint32_t offsets[GBM_MAX_PLANES];
+ uint64_t format_modifiers[GBM_MAX_PLANES];
+};
+
+struct gbm_bo *
+gbm_bo_import(struct gbm_device *gbm, uint32_t type,
+ void *buffer, uint32_t usage);
+
+/**
+ * Flags to indicate the type of mapping for the buffer - these are
+ * passed into gbm_bo_map(). The caller must set the union of all the
+ * flags that are appropriate.
+ *
+ * These flags are independent of the GBM_BO_USE_* creation flags. However,
+ * mapping the buffer may require copying to/from a staging buffer.
+ *
+ * See also: pipe_transfer_usage
+ */
+enum gbm_bo_transfer_flags {
+ /**
+ * Buffer contents read back (or accessed directly) at transfer
+ * create time.
+ */
+ GBM_BO_TRANSFER_READ = (1 << 0),
+ /**
+ * Buffer contents will be written back at unmap time
+ * (or modified as a result of being accessed directly).
+ */
+ GBM_BO_TRANSFER_WRITE = (1 << 1),
+ /**
+ * Read/modify/write
+ */
+ GBM_BO_TRANSFER_READ_WRITE = (GBM_BO_TRANSFER_READ | GBM_BO_TRANSFER_WRITE),
+};
+
+void *
+gbm_bo_map(struct gbm_bo *bo,
+ uint32_t x, uint32_t y, uint32_t width, uint32_t height,
+ uint32_t flags, uint32_t *stride, void **map_data, size_t plane);
+
+void
+gbm_bo_unmap(struct gbm_bo *bo, void *map_data);
+
+uint32_t
+gbm_bo_get_width(struct gbm_bo *bo);
+
+uint32_t
+gbm_bo_get_height(struct gbm_bo *bo);
+
+uint32_t
+gbm_bo_get_stride(struct gbm_bo *bo);
+
+/* Tegra bringup hack to pass tiling parameters at EGLImage creation. */
+uint32_t
+gbm_bo_get_stride_or_tiling(struct gbm_bo *bo);
+
+uint32_t
+gbm_bo_get_format(struct gbm_bo *bo);
+
+uint64_t
+gbm_bo_get_format_modifier(struct gbm_bo *bo);
+
+struct gbm_device *
+gbm_bo_get_device(struct gbm_bo *bo);
+
+union gbm_bo_handle
+gbm_bo_get_handle(struct gbm_bo *bo);
+
+int
+gbm_bo_get_fd(struct gbm_bo *bo);
+
+size_t
+gbm_bo_get_num_planes(struct gbm_bo *bo);
+
+union gbm_bo_handle
+gbm_bo_get_plane_handle(struct gbm_bo *bo, size_t plane);
+
+int
+gbm_bo_get_plane_fd(struct gbm_bo *bo, size_t plane);
+
+uint32_t
+gbm_bo_get_plane_offset(struct gbm_bo *bo, size_t plane);
+
+uint32_t
+gbm_bo_get_plane_size(struct gbm_bo *bo, size_t plane);
+
+uint32_t
+gbm_bo_get_plane_stride(struct gbm_bo *bo, size_t plane);
+
+uint64_t
+gbm_bo_get_plane_format_modifier(struct gbm_bo *bo, size_t plane);
+
+void
+gbm_bo_set_user_data(struct gbm_bo *bo, void *data,
+ void (*destroy_user_data)(struct gbm_bo *, void *));
+
+void *
+gbm_bo_get_user_data(struct gbm_bo *bo);
+
+void
+gbm_bo_destroy(struct gbm_bo *bo);
+
+struct gbm_surface *
+gbm_surface_create(struct gbm_device *gbm,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t flags);
+
+struct gbm_bo *
+gbm_surface_lock_front_buffer(struct gbm_surface *surface);
+
+void
+gbm_surface_release_buffer(struct gbm_surface *surface, struct gbm_bo *bo);
+
+int
+gbm_surface_has_free_buffers(struct gbm_surface *surface);
+
+void
+gbm_surface_destroy(struct gbm_surface *surface);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/chromium/third_party/minigbm/src/gbm.pc b/chromium/third_party/minigbm/src/gbm.pc
new file mode 100644
index 00000000000..e99ac83d2b2
--- /dev/null
+++ b/chromium/third_party/minigbm/src/gbm.pc
@@ -0,0 +1,10 @@
+prefix=/usr
+exec_prefix=${prefix}
+includedir=${prefix}/include
+libdir=${exec_prefix}/lib
+
+Name: libgbm
+Description: A small gbm implementation
+Version: 0
+Cflags: -I${includedir}
+Libs: -L${libdir} -lgbm
diff --git a/chromium/third_party/minigbm/src/gbm_helpers.c b/chromium/third_party/minigbm/src/gbm_helpers.c
new file mode 100644
index 00000000000..529d7fe73b0
--- /dev/null
+++ b/chromium/third_party/minigbm/src/gbm_helpers.c
@@ -0,0 +1,35 @@
+/*
+ * 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 <stddef.h>
+#include <stdio.h>
+
+#include "drv.h"
+#include "gbm.h"
+
+uint64_t gbm_convert_flags(uint32_t flags)
+{
+ uint64_t usage = BO_USE_NONE;
+
+ if (flags & GBM_BO_USE_SCANOUT)
+ usage |= BO_USE_SCANOUT;
+ if (flags & GBM_BO_USE_CURSOR)
+ usage |= BO_USE_CURSOR;
+ if (flags & GBM_BO_USE_CURSOR_64X64)
+ usage |= BO_USE_CURSOR_64X64;
+ if (flags & GBM_BO_USE_RENDERING)
+ usage |= BO_USE_RENDERING;
+ if (flags & GBM_BO_USE_TEXTURING)
+ usage |= BO_USE_TEXTURE;
+ if (flags & GBM_BO_USE_LINEAR)
+ usage |= BO_USE_LINEAR;
+ if (flags & GBM_BO_USE_CAMERA_WRITE)
+ usage |= BO_USE_CAMERA_WRITE;
+ if (flags & GBM_BO_USE_CAMERA_READ)
+ usage |= BO_USE_CAMERA_READ;
+
+ return usage;
+}
diff --git a/chromium/third_party/minigbm/src/gbm_helpers.h b/chromium/third_party/minigbm/src/gbm_helpers.h
new file mode 100644
index 00000000000..48ff3913736
--- /dev/null
+++ b/chromium/third_party/minigbm/src/gbm_helpers.h
@@ -0,0 +1,12 @@
+/*
+ * 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_HELPERS_H
+#define GBM_HELPERS_H
+
+uint64_t gbm_convert_flags(uint32_t flags);
+
+#endif
diff --git a/chromium/third_party/minigbm/src/gbm_priv.h b/chromium/third_party/minigbm/src/gbm_priv.h
new file mode 100644
index 00000000000..3dc1e594458
--- /dev/null
+++ b/chromium/third_party/minigbm/src/gbm_priv.h
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+#ifndef GBM_PRIV_H
+#define GBM_PRIV_H
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include "drv.h"
+#include "gbm.h"
+
+struct gbm_device {
+ struct driver *drv;
+};
+
+struct gbm_surface {
+};
+
+struct gbm_bo {
+ struct gbm_device *gbm;
+ struct bo *bo;
+ uint32_t gbm_format;
+ void *user_data;
+ void (*destroy_user_data)(struct gbm_bo *, void *);
+};
+
+#endif
diff --git a/chromium/third_party/minigbm/src/gma500.c b/chromium/third_party/minigbm/src/gma500.c
new file mode 100644
index 00000000000..5b08bc32b09
--- /dev/null
+++ b/chromium/third_party/minigbm/src/gma500.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+static const uint32_t render_target_formats[] = { DRM_FORMAT_RGBX8888 };
+
+static int gma500_init(struct driver *drv)
+{
+ int ret;
+ ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+ &LINEAR_METADATA, BO_USE_RENDER_MASK);
+ if (ret)
+ return ret;
+
+ return drv_modify_linear_combinations(drv);
+}
+
+struct backend backend_gma500 = {
+ .name = "gma500",
+ .init = gma500_init,
+ .bo_create = drv_dumb_bo_create,
+ .bo_destroy = drv_dumb_bo_destroy,
+ .bo_import = drv_prime_bo_import,
+ .bo_map = drv_dumb_bo_map,
+};
diff --git a/chromium/third_party/minigbm/src/helpers.c b/chromium/third_party/minigbm/src/helpers.c
new file mode 100644
index 00000000000..238563de923
--- /dev/null
+++ b/chromium/third_party/minigbm/src/helpers.c
@@ -0,0 +1,549 @@
+/*
+ * Copyright 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+static uint32_t subsample_stride(uint32_t stride, uint32_t format, size_t plane)
+{
+
+ if (plane != 0) {
+ switch (format) {
+ case DRM_FORMAT_YVU420:
+ case DRM_FORMAT_YVU420_ANDROID:
+ stride = DIV_ROUND_UP(stride, 2);
+ break;
+ }
+ }
+
+ return stride;
+}
+
+static uint32_t bpp_from_format(uint32_t format, size_t plane)
+{
+ assert(plane < drv_num_planes_from_format(format));
+
+ switch (format) {
+ case DRM_FORMAT_BGR233:
+ case DRM_FORMAT_C8:
+ case DRM_FORMAT_R8:
+ case DRM_FORMAT_RGB332:
+ case DRM_FORMAT_YVU420:
+ case DRM_FORMAT_YVU420_ANDROID:
+ return 8;
+
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_NV21:
+ return (plane == 0) ? 8 : 4;
+
+ case DRM_FORMAT_ABGR1555:
+ case DRM_FORMAT_ABGR4444:
+ case DRM_FORMAT_ARGB1555:
+ case DRM_FORMAT_ARGB4444:
+ case DRM_FORMAT_BGR565:
+ case DRM_FORMAT_BGRA4444:
+ case DRM_FORMAT_BGRA5551:
+ case DRM_FORMAT_BGRX4444:
+ case DRM_FORMAT_BGRX5551:
+ case DRM_FORMAT_GR88:
+ case DRM_FORMAT_RG88:
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_RGBA4444:
+ case DRM_FORMAT_RGBA5551:
+ case DRM_FORMAT_RGBX4444:
+ case DRM_FORMAT_RGBX5551:
+ case DRM_FORMAT_UYVY:
+ case DRM_FORMAT_VYUY:
+ case DRM_FORMAT_XBGR1555:
+ case DRM_FORMAT_XBGR4444:
+ case DRM_FORMAT_XRGB1555:
+ case DRM_FORMAT_XRGB4444:
+ case DRM_FORMAT_YUYV:
+ case DRM_FORMAT_YVYU:
+ return 16;
+
+ case DRM_FORMAT_BGR888:
+ case DRM_FORMAT_RGB888:
+ return 24;
+
+ case DRM_FORMAT_ABGR2101010:
+ case DRM_FORMAT_ABGR8888:
+ case DRM_FORMAT_ARGB2101010:
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_AYUV:
+ case DRM_FORMAT_BGRA1010102:
+ case DRM_FORMAT_BGRA8888:
+ case DRM_FORMAT_BGRX1010102:
+ case DRM_FORMAT_BGRX8888:
+ case DRM_FORMAT_RGBA1010102:
+ case DRM_FORMAT_RGBA8888:
+ case DRM_FORMAT_RGBX1010102:
+ case DRM_FORMAT_RGBX8888:
+ case DRM_FORMAT_XBGR2101010:
+ case DRM_FORMAT_XBGR8888:
+ case DRM_FORMAT_XRGB2101010:
+ case DRM_FORMAT_XRGB8888:
+ return 32;
+ }
+
+ fprintf(stderr, "drv: UNKNOWN FORMAT %d\n", format);
+ return 0;
+}
+
+uint32_t drv_bo_get_stride_in_pixels(struct bo *bo)
+{
+ uint32_t bytes_per_pixel = DIV_ROUND_UP(bpp_from_format(bo->format, 0), 8);
+ return DIV_ROUND_UP(bo->strides[0], bytes_per_pixel);
+}
+
+/*
+ * This function returns the stride for a given format, width and plane.
+ */
+uint32_t drv_stride_from_format(uint32_t format, uint32_t width, size_t plane)
+{
+ uint32_t stride = DIV_ROUND_UP(width * bpp_from_format(format, plane), 8);
+
+ /*
+ * The stride of Android YV12 buffers is required to be aligned to 16 bytes
+ * (see <system/graphics.h>).
+ */
+ if (format == DRM_FORMAT_YVU420_ANDROID)
+ stride = (plane == 0) ? ALIGN(stride, 32) : ALIGN(stride, 16);
+
+ return stride;
+}
+
+/*
+ * This function fills in the buffer object given the driver aligned stride of
+ * the first plane, height and a format. This function assumes there is just
+ * one kernel buffer per buffer object.
+ */
+int drv_bo_from_format(struct bo *bo, uint32_t stride, uint32_t aligned_height, uint32_t format)
+{
+
+ size_t p, num_planes;
+ uint32_t offset = 0;
+
+ num_planes = drv_num_planes_from_format(format);
+ assert(num_planes);
+
+ /*
+ * HAL_PIXEL_FORMAT_YV12 requires that (see <system/graphics.h>):
+ * - the aligned height is same as the buffer's height.
+ * - the chroma stride is 16 bytes aligned, i.e., the luma's strides
+ * is 32 bytes aligned.
+ */
+ if (format == DRM_FORMAT_YVU420_ANDROID) {
+ assert(aligned_height == bo->height);
+ assert(stride == ALIGN(stride, 32));
+ }
+
+ for (p = 0; p < num_planes; p++) {
+ bo->strides[p] = subsample_stride(stride, format, p);
+ bo->sizes[p] = drv_size_from_format(format, bo->strides[p], aligned_height, p);
+ bo->offsets[p] = offset;
+ offset += bo->sizes[p];
+ }
+
+ bo->total_size = offset;
+ return 0;
+}
+
+int drv_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+ uint32_t flags)
+{
+ int ret;
+ size_t plane;
+ uint32_t aligned_width, aligned_height;
+ struct drm_mode_create_dumb create_dumb;
+
+ aligned_width = width;
+ aligned_height = height;
+ if (format == DRM_FORMAT_YVU420_ANDROID) {
+ /*
+ * Align width to 32 pixels, so chroma strides are 16 bytes as
+ * Android requires.
+ */
+ aligned_width = ALIGN(width, 32);
+ }
+
+ if (format == DRM_FORMAT_YVU420_ANDROID || format == DRM_FORMAT_YVU420) {
+ aligned_height = 3 * DIV_ROUND_UP(height, 2);
+ }
+
+ memset(&create_dumb, 0, sizeof(create_dumb));
+ create_dumb.height = aligned_height;
+ create_dumb.width = aligned_width;
+ create_dumb.bpp = bpp_from_format(format, 0);
+ create_dumb.flags = 0;
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
+ if (ret) {
+ fprintf(stderr, "drv: DRM_IOCTL_MODE_CREATE_DUMB failed\n");
+ return ret;
+ }
+
+ drv_bo_from_format(bo, create_dumb.pitch, height, format);
+
+ for (plane = 0; plane < bo->num_planes; plane++)
+ bo->handles[plane].u32 = create_dumb.handle;
+
+ bo->total_size = create_dumb.size;
+ return 0;
+}
+
+int drv_dumb_bo_destroy(struct bo *bo)
+{
+ struct drm_mode_destroy_dumb destroy_dumb;
+ int ret;
+
+ memset(&destroy_dumb, 0, sizeof(destroy_dumb));
+ destroy_dumb.handle = bo->handles[0].u32;
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
+ if (ret) {
+ fprintf(stderr, "drv: DRM_IOCTL_MODE_DESTROY_DUMB failed (handle=%x)\n",
+ bo->handles[0].u32);
+ return ret;
+ }
+
+ return 0;
+}
+
+int drv_gem_bo_destroy(struct bo *bo)
+{
+ struct drm_gem_close gem_close;
+ int ret, error = 0;
+ size_t plane, i;
+
+ for (plane = 0; plane < bo->num_planes; plane++) {
+ for (i = 0; i < plane; i++)
+ if (bo->handles[i].u32 == bo->handles[plane].u32)
+ break;
+ /* Make sure close hasn't already been called on this handle */
+ if (i != plane)
+ continue;
+
+ memset(&gem_close, 0, sizeof(gem_close));
+ gem_close.handle = bo->handles[plane].u32;
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
+ if (ret) {
+ fprintf(stderr, "drv: DRM_IOCTL_GEM_CLOSE failed (handle=%x) error %d\n",
+ bo->handles[plane].u32, ret);
+ error = ret;
+ }
+ }
+
+ return error;
+}
+
+int drv_prime_bo_import(struct bo *bo, struct drv_import_fd_data *data)
+{
+ int ret;
+ size_t plane;
+ struct drm_prime_handle prime_handle;
+
+ for (plane = 0; plane < bo->num_planes; plane++) {
+ memset(&prime_handle, 0, sizeof(prime_handle));
+ prime_handle.fd = data->fds[plane];
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &prime_handle);
+
+ if (ret) {
+ fprintf(stderr, "drv: DRM_IOCTL_PRIME_FD_TO_HANDLE failed (fd=%u)\n",
+ prime_handle.fd);
+
+ /*
+ * Need to call GEM close on planes that were opened,
+ * if any. Adjust the num_planes variable to be the
+ * plane that failed, so GEM close will be called on
+ * planes before that plane.
+ */
+ bo->num_planes = plane;
+ drv_gem_bo_destroy(bo);
+ return ret;
+ }
+
+ bo->handles[plane].u32 = prime_handle.handle;
+ }
+
+ for (plane = 0; plane < bo->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);
+ }
+
+ return 0;
+}
+
+void *drv_dumb_bo_map(struct bo *bo, struct map_info *data, size_t plane, int prot)
+{
+ int ret;
+ size_t i;
+ struct drm_mode_map_dumb map_dumb;
+
+ memset(&map_dumb, 0, sizeof(map_dumb));
+ map_dumb.handle = bo->handles[plane].u32;
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb);
+ if (ret) {
+ fprintf(stderr, "drv: DRM_IOCTL_MODE_MAP_DUMB failed \n");
+ return MAP_FAILED;
+ }
+
+ for (i = 0; i < bo->num_planes; i++)
+ if (bo->handles[i].u32 == bo->handles[plane].u32)
+ data->length += bo->sizes[i];
+
+ return mmap(0, data->length, prot, MAP_SHARED, bo->drv->fd, map_dumb.offset);
+}
+
+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));
+}
+
+uint32_t drv_log_base2(uint32_t value)
+{
+ int ret = 0;
+
+ while (value >>= 1)
+ ++ret;
+
+ return ret;
+}
+
+int drv_add_combination(struct driver *drv, uint32_t format, struct format_metadata *metadata,
+ uint64_t usage)
+{
+ struct combinations *combos = &drv->backend->combos;
+ if (combos->size >= combos->allocations) {
+ struct combination *new_data;
+ combos->allocations *= 2;
+ new_data = realloc(combos->data, combos->allocations * sizeof(*combos->data));
+ if (!new_data)
+ return -ENOMEM;
+
+ combos->data = new_data;
+ }
+
+ combos->data[combos->size].format = format;
+ combos->data[combos->size].metadata.priority = metadata->priority;
+ combos->data[combos->size].metadata.tiling = metadata->tiling;
+ combos->data[combos->size].metadata.modifier = metadata->modifier;
+ combos->data[combos->size].usage = usage;
+ combos->size++;
+ return 0;
+}
+
+int drv_add_combinations(struct driver *drv, const uint32_t *formats, uint32_t num_formats,
+ struct format_metadata *metadata, uint64_t usage)
+{
+ int ret;
+ uint32_t i;
+ for (i = 0; i < num_formats; i++) {
+ ret = drv_add_combination(drv, formats[i], metadata, usage);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+void drv_modify_combination(struct driver *drv, uint32_t format, struct format_metadata *metadata,
+ uint64_t usage)
+{
+ uint32_t i;
+ struct combination *combo;
+ /* Attempts to add the specified usage to an existing combination. */
+ for (i = 0; i < drv->backend->combos.size; i++) {
+ combo = &drv->backend->combos.data[i];
+ if (combo->format == format && combo->metadata.tiling == metadata->tiling &&
+ combo->metadata.modifier == metadata->modifier)
+ combo->usage |= usage;
+ }
+}
+
+struct kms_item *drv_query_kms(struct driver *drv, uint32_t *num_items)
+{
+ uint64_t flag, usage;
+ struct kms_item *items;
+ uint32_t i, j, k, allocations, item_size;
+
+ drmModePlanePtr plane;
+ drmModePropertyPtr prop;
+ drmModePlaneResPtr resources;
+ drmModeObjectPropertiesPtr props;
+
+ /* Start with a power of 2 number of allocations. */
+ allocations = 2;
+ item_size = 0;
+ items = calloc(allocations, sizeof(*items));
+ if (!items)
+ goto out;
+
+ /*
+ * The ability to return universal planes is only complete on
+ * ChromeOS kernel versions >= v3.18. The SET_CLIENT_CAP ioctl
+ * therefore might return an error code, so don't check it. If it
+ * fails, it'll just return the plane list as overlay planes, which is
+ * fine in our case (our drivers already have cursor bits set).
+ * modetest in libdrm does the same thing.
+ */
+ drmSetClientCap(drv->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
+
+ resources = drmModeGetPlaneResources(drv->fd);
+ if (!resources)
+ goto out;
+
+ for (i = 0; i < resources->count_planes; i++) {
+ plane = drmModeGetPlane(drv->fd, resources->planes[i]);
+ if (!plane)
+ goto out;
+
+ props = drmModeObjectGetProperties(drv->fd, plane->plane_id, DRM_MODE_OBJECT_PLANE);
+ if (!props)
+ goto out;
+
+ for (j = 0; j < props->count_props; j++) {
+ prop = drmModeGetProperty(drv->fd, props->props[j]);
+ if (prop) {
+ if (strcmp(prop->name, "type") == 0) {
+ flag = props->prop_values[j];
+ }
+
+ drmModeFreeProperty(prop);
+ }
+ }
+
+ switch (flag) {
+ case DRM_PLANE_TYPE_OVERLAY:
+ case DRM_PLANE_TYPE_PRIMARY:
+ usage = BO_USE_SCANOUT;
+ break;
+ case DRM_PLANE_TYPE_CURSOR:
+ usage = BO_USE_CURSOR;
+ break;
+ default:
+ assert(0);
+ }
+
+ for (j = 0; j < plane->count_formats; j++) {
+ bool found = false;
+ for (k = 0; k < item_size; k++) {
+ if (items[k].format == plane->formats[j] &&
+ items[k].modifier == DRM_FORMAT_MOD_NONE) {
+ items[k].usage |= usage;
+ found = true;
+ break;
+ }
+ }
+
+ if (!found && item_size >= allocations) {
+ struct kms_item *new_data = NULL;
+ allocations *= 2;
+ new_data = realloc(items, allocations * sizeof(*items));
+ if (!new_data) {
+ item_size = 0;
+ goto out;
+ }
+
+ items = new_data;
+ }
+
+ if (!found) {
+ items[item_size].format = plane->formats[j];
+ items[item_size].modifier = DRM_FORMAT_MOD_NONE;
+ items[item_size].usage = usage;
+ item_size++;
+ }
+ }
+
+ drmModeFreeObjectProperties(props);
+ drmModeFreePlane(plane);
+ }
+
+ drmModeFreePlaneResources(resources);
+out:
+ if (items && item_size == 0) {
+ free(items);
+ items = NULL;
+ }
+
+ *num_items = item_size;
+ return items;
+}
+
+int drv_modify_linear_combinations(struct driver *drv)
+{
+ uint32_t i, j, num_items;
+ struct kms_item *items;
+ struct combination *combo;
+
+ /*
+ * All current drivers can scanout linear XRGB8888/ARGB8888 as a primary
+ * plane and as a cursor. Some drivers don't support
+ * drmModeGetPlaneResources, so add the combination here. Note that the
+ * kernel disregards the alpha component of ARGB unless it's an overlay
+ * plane.
+ */
+ drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &LINEAR_METADATA,
+ BO_USE_CURSOR | BO_USE_SCANOUT);
+ drv_modify_combination(drv, DRM_FORMAT_ARGB8888, &LINEAR_METADATA,
+ BO_USE_CURSOR | BO_USE_SCANOUT);
+
+ items = drv_query_kms(drv, &num_items);
+ if (!items || !num_items)
+ return 0;
+
+ for (i = 0; i < num_items; i++) {
+ for (j = 0; j < drv->backend->combos.size; j++) {
+ combo = &drv->backend->combos.data[j];
+ if (items[i].format == combo->format)
+ combo->usage |= BO_USE_SCANOUT;
+ }
+ }
+
+ free(items);
+ return 0;
+}
diff --git a/chromium/third_party/minigbm/src/helpers.h b/chromium/third_party/minigbm/src/helpers.h
new file mode 100644
index 00000000000..dc1a7c06233
--- /dev/null
+++ b/chromium/third_party/minigbm/src/helpers.h
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+#ifndef HELPERS_H
+#define HELPERS_H
+
+#include "drv.h"
+
+uint32_t drv_stride_from_format(uint32_t format, uint32_t width, size_t plane);
+int drv_bo_from_format(struct bo *bo, uint32_t stride, uint32_t aligned_height, uint32_t format);
+int drv_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+ uint32_t flags);
+int drv_dumb_bo_destroy(struct bo *bo);
+int drv_gem_bo_destroy(struct bo *bo);
+int drv_prime_bo_import(struct bo *bo, struct drv_import_fd_data *data);
+void *drv_dumb_bo_map(struct bo *bo, struct map_info *data, size_t plane, int prot);
+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);
+uint32_t drv_log_base2(uint32_t value);
+int drv_add_combination(struct driver *drv, uint32_t format, struct format_metadata *metadata,
+ uint64_t usage);
+int drv_add_combinations(struct driver *drv, const uint32_t *formats, uint32_t num_formats,
+ struct format_metadata *metadata, uint64_t usage);
+void drv_modify_combination(struct driver *drv, uint32_t format, struct format_metadata *metadata,
+ uint64_t usage);
+struct kms_item *drv_query_kms(struct driver *drv, uint32_t *num_items);
+int drv_modify_linear_combinations(struct driver *drv);
+#endif
diff --git a/chromium/third_party/minigbm/src/i915.c b/chromium/third_party/minigbm/src/i915.c
new file mode 100644
index 00000000000..fe162f16d50
--- /dev/null
+++ b/chromium/third_party/minigbm/src/i915.c
@@ -0,0 +1,513 @@
+/*
+ * 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_I915
+
+#include <errno.h>
+#include <i915_drm.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <xf86drm.h>
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+#define I915_CACHELINE_SIZE 64
+#define I915_CACHELINE_MASK (I915_CACHELINE_SIZE - 1)
+
+static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB1555, DRM_FORMAT_ABGR8888,
+ DRM_FORMAT_ARGB8888, DRM_FORMAT_RGB565,
+ DRM_FORMAT_XBGR8888, DRM_FORMAT_XRGB1555,
+ DRM_FORMAT_XRGB8888 };
+
+static const uint32_t tileable_texture_source_formats[] = { DRM_FORMAT_GR88, DRM_FORMAT_NV12,
+ DRM_FORMAT_R8, DRM_FORMAT_UYVY,
+ DRM_FORMAT_YUYV };
+
+static const uint32_t texture_source_formats[] = { DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID };
+
+struct i915_device {
+ uint32_t gen;
+ int32_t has_llc;
+};
+
+static uint32_t i915_get_gen(int device_id)
+{
+ const uint16_t gen3_ids[] = { 0x2582, 0x2592, 0x2772, 0x27A2, 0x27AE,
+ 0x29C2, 0x29B2, 0x29D2, 0xA001, 0xA011 };
+ unsigned i;
+ for (i = 0; i < ARRAY_SIZE(gen3_ids); i++)
+ if (gen3_ids[i] == device_id)
+ return 3;
+
+ return 4;
+}
+
+static int i915_add_kms_item(struct driver *drv, const struct kms_item *item)
+{
+ uint32_t i;
+ struct combination *combo;
+
+ /*
+ * Older hardware can't scanout Y-tiled formats. Newer devices can, and
+ * report this functionality via format modifiers.
+ */
+ for (i = 0; i < drv->backend->combos.size; i++) {
+ combo = &drv->backend->combos.data[i];
+ if (combo->format != item->format)
+ continue;
+
+ if (item->modifier == DRM_FORMAT_MOD_NONE &&
+ combo->metadata.tiling == I915_TILING_X) {
+ /*
+ * FIXME: drv_query_kms() does not report the available modifiers
+ * yet, but we know that all hardware can scanout from X-tiled
+ * buffers, so let's add this to our combinations, except for
+ * cursor, which must not be tiled.
+ */
+ combo->usage |= item->usage & ~BO_USE_CURSOR;
+ }
+
+ if (combo->metadata.modifier == item->modifier)
+ combo->usage |= item->usage;
+ }
+
+ return 0;
+}
+
+static int i915_add_combinations(struct driver *drv)
+{
+ int ret;
+ uint32_t i, num_items;
+ struct kms_item *items;
+ struct format_metadata metadata;
+ uint64_t render_flags, texture_flags;
+
+ render_flags = BO_USE_RENDER_MASK;
+ texture_flags = BO_USE_TEXTURE_MASK;
+
+ metadata.tiling = I915_TILING_NONE;
+ metadata.priority = 1;
+ metadata.modifier = DRM_FORMAT_MOD_NONE;
+
+ ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+ &metadata, render_flags);
+ if (ret)
+ return ret;
+
+ ret = drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats),
+ &metadata, texture_flags);
+ if (ret)
+ return ret;
+
+ ret = drv_add_combinations(drv, tileable_texture_source_formats,
+ ARRAY_SIZE(tileable_texture_source_formats), &metadata,
+ texture_flags);
+ if (ret)
+ return ret;
+
+ drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT);
+ drv_modify_combination(drv, DRM_FORMAT_ARGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT);
+
+ /* IPU3 camera ISP supports only NV12 output. */
+ drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata,
+ BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
+ /*
+ * R8 format is used for Android's HAL_PIXEL_FORMAT_BLOB and is used for JPEG snapshots
+ * from camera.
+ */
+ drv_modify_combination(drv, DRM_FORMAT_R8, &metadata,
+ BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
+
+ render_flags &= ~BO_USE_RENDERSCRIPT;
+ render_flags &= ~BO_USE_SW_WRITE_OFTEN;
+ render_flags &= ~BO_USE_SW_READ_OFTEN;
+ render_flags &= ~BO_USE_LINEAR;
+
+ texture_flags &= ~BO_USE_RENDERSCRIPT;
+ texture_flags &= ~BO_USE_SW_WRITE_OFTEN;
+ texture_flags &= ~BO_USE_SW_READ_OFTEN;
+ texture_flags &= ~BO_USE_LINEAR;
+
+ metadata.tiling = I915_TILING_X;
+ metadata.priority = 2;
+ metadata.modifier = I915_FORMAT_MOD_X_TILED;
+
+ ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+ &metadata, render_flags);
+ if (ret)
+ return ret;
+
+ ret = drv_add_combinations(drv, tileable_texture_source_formats,
+ ARRAY_SIZE(tileable_texture_source_formats), &metadata,
+ texture_flags);
+ if (ret)
+ return ret;
+
+ metadata.tiling = I915_TILING_Y;
+ metadata.priority = 3;
+ metadata.modifier = I915_FORMAT_MOD_Y_TILED;
+
+ ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+ &metadata, render_flags);
+ if (ret)
+ return ret;
+
+ ret = drv_add_combinations(drv, tileable_texture_source_formats,
+ ARRAY_SIZE(tileable_texture_source_formats), &metadata,
+ texture_flags);
+ if (ret)
+ return ret;
+
+ items = drv_query_kms(drv, &num_items);
+ if (!items || !num_items)
+ return 0;
+
+ for (i = 0; i < num_items; i++) {
+ ret = i915_add_kms_item(drv, &items[i]);
+ if (ret) {
+ free(items);
+ return ret;
+ }
+ }
+
+ free(items);
+ return 0;
+}
+
+static int i915_align_dimensions(struct bo *bo, uint32_t tiling, uint32_t *stride,
+ uint32_t *aligned_height)
+{
+ struct i915_device *i915 = bo->drv->priv;
+ uint32_t horizontal_alignment = 4;
+ uint32_t vertical_alignment = 4;
+
+ switch (tiling) {
+ default:
+ case I915_TILING_NONE:
+ horizontal_alignment = 64;
+ break;
+
+ case I915_TILING_X:
+ horizontal_alignment = 512;
+ vertical_alignment = 8;
+ break;
+
+ case I915_TILING_Y:
+ if (i915->gen == 3) {
+ horizontal_alignment = 512;
+ vertical_alignment = 8;
+ } else {
+ horizontal_alignment = 128;
+ vertical_alignment = 32;
+ }
+ break;
+ }
+
+ /*
+ * The alignment calculated above is based on the full size luma plane and to have chroma
+ * planes properly aligned with subsampled formats, we need to multiply luma alignment by
+ * subsampling factor.
+ */
+ switch (bo->format) {
+ case DRM_FORMAT_YVU420_ANDROID:
+ case DRM_FORMAT_YVU420:
+ horizontal_alignment *= 2;
+ /* Fall through */
+ case DRM_FORMAT_NV12:
+ vertical_alignment *= 2;
+ break;
+ }
+
+ *aligned_height = ALIGN(bo->height, vertical_alignment);
+ if (i915->gen > 3) {
+ *stride = ALIGN(*stride, horizontal_alignment);
+ } else {
+ while (*stride > horizontal_alignment)
+ horizontal_alignment <<= 1;
+
+ *stride = horizontal_alignment;
+ }
+
+ if (i915->gen <= 3 && *stride > 8192)
+ return -EINVAL;
+
+ return 0;
+}
+
+static void i915_clflush(void *start, size_t size)
+{
+ void *p = (void *)(((uintptr_t)start) & ~I915_CACHELINE_MASK);
+ void *end = (void *)((uintptr_t)start + size);
+
+ __builtin_ia32_mfence();
+ while (p < end) {
+ __builtin_ia32_clflush(p);
+ p = (void *)((uintptr_t)p + I915_CACHELINE_SIZE);
+ }
+}
+
+static int i915_init(struct driver *drv)
+{
+ int ret;
+ int device_id;
+ struct i915_device *i915;
+ drm_i915_getparam_t get_param;
+
+ i915 = calloc(1, sizeof(*i915));
+ if (!i915)
+ return -ENOMEM;
+
+ memset(&get_param, 0, sizeof(get_param));
+ get_param.param = I915_PARAM_CHIPSET_ID;
+ get_param.value = &device_id;
+ ret = drmIoctl(drv->fd, DRM_IOCTL_I915_GETPARAM, &get_param);
+ if (ret) {
+ fprintf(stderr, "drv: Failed to get I915_PARAM_CHIPSET_ID\n");
+ free(i915);
+ return -EINVAL;
+ }
+
+ i915->gen = i915_get_gen(device_id);
+
+ memset(&get_param, 0, sizeof(get_param));
+ get_param.param = I915_PARAM_HAS_LLC;
+ get_param.value = &i915->has_llc;
+ ret = drmIoctl(drv->fd, DRM_IOCTL_I915_GETPARAM, &get_param);
+ if (ret) {
+ fprintf(stderr, "drv: Failed to get I915_PARAM_HAS_LLC\n");
+ free(i915);
+ return -EINVAL;
+ }
+
+ drv->priv = i915;
+
+ return i915_add_combinations(drv);
+}
+
+static int i915_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+ uint32_t flags)
+{
+ int ret;
+ size_t plane;
+ uint32_t stride;
+ struct drm_i915_gem_create gem_create;
+ struct drm_i915_gem_set_tiling gem_set_tiling;
+ struct combination *combo;
+
+ combo = drv_get_combination(bo->drv, format, flags);
+ if (!combo)
+ return -EINVAL;
+
+ bo->tiling = combo->metadata.tiling;
+
+ stride = drv_stride_from_format(format, width, 0);
+
+ ret = i915_align_dimensions(bo, bo->tiling, &stride, &height);
+ if (ret)
+ return ret;
+
+ /*
+ * HAL_PIXEL_FORMAT_YV12 requires the buffer height not be aligned, but we need to keep
+ * total size as with aligned height to ensure enough padding space after each plane to
+ * satisfy GPU alignment requirements.
+ *
+ * We do it by first calling drv_bo_from_format() with aligned height and
+ * DRM_FORMAT_YVU420, which allows height alignment, saving the total size it calculates
+ * and then calling it again with requested parameters.
+ *
+ * This relies on the fact that i965 driver uses separate surfaces for each plane and
+ * contents of padding bytes is not affected, as it is only used to satisfy GPU cache
+ * requests.
+ *
+ * This is enforced by Mesa in src/intel/isl/isl_gen8.c, inside
+ * isl_gen8_choose_image_alignment_el(), which is used for GEN9 and GEN8.
+ */
+ if (format == DRM_FORMAT_YVU420_ANDROID) {
+ uint32_t unaligned_height = bo->height;
+ size_t total_size;
+
+ drv_bo_from_format(bo, stride, height, DRM_FORMAT_YVU420);
+ total_size = bo->total_size;
+ drv_bo_from_format(bo, stride, unaligned_height, format);
+ bo->total_size = total_size;
+ } else {
+ drv_bo_from_format(bo, stride, height, format);
+ }
+
+ /*
+ * Quoting Mesa ISL library:
+ *
+ * - For linear surfaces, additional padding of 64 bytes is required at
+ * the bottom of the surface. This is in addition to the padding
+ * required above.
+ */
+ if (bo->tiling == I915_TILING_NONE)
+ bo->total_size += 64;
+
+ memset(&gem_create, 0, sizeof(gem_create));
+ gem_create.size = bo->total_size;
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create);
+ if (ret) {
+ fprintf(stderr, "drv: DRM_IOCTL_I915_GEM_CREATE failed (size=%llu)\n",
+ gem_create.size);
+ return ret;
+ }
+
+ for (plane = 0; plane < bo->num_planes; plane++)
+ bo->handles[plane].u32 = gem_create.handle;
+
+ memset(&gem_set_tiling, 0, sizeof(gem_set_tiling));
+ gem_set_tiling.handle = bo->handles[0].u32;
+ gem_set_tiling.tiling_mode = bo->tiling;
+ gem_set_tiling.stride = bo->strides[0];
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_SET_TILING, &gem_set_tiling);
+ if (ret) {
+ struct drm_gem_close gem_close;
+ memset(&gem_close, 0, sizeof(gem_close));
+ gem_close.handle = bo->handles[0].u32;
+ drmIoctl(bo->drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
+
+ fprintf(stderr, "drv: DRM_IOCTL_I915_GEM_SET_TILING failed with %d", errno);
+ return -errno;
+ }
+
+ return 0;
+}
+
+static void i915_close(struct driver *drv)
+{
+ free(drv->priv);
+ drv->priv = NULL;
+}
+
+static int i915_bo_import(struct bo *bo, struct drv_import_fd_data *data)
+{
+ int ret;
+ struct drm_i915_gem_get_tiling gem_get_tiling;
+
+ ret = drv_prime_bo_import(bo, data);
+ if (ret)
+ return ret;
+
+ /* TODO(gsingh): export modifiers and get rid of backdoor tiling. */
+ memset(&gem_get_tiling, 0, sizeof(gem_get_tiling));
+ gem_get_tiling.handle = bo->handles[0].u32;
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_GET_TILING, &gem_get_tiling);
+ if (ret) {
+ drv_gem_bo_destroy(bo);
+ fprintf(stderr, "drv: DRM_IOCTL_I915_GEM_GET_TILING failed.");
+ return ret;
+ }
+
+ bo->tiling = gem_get_tiling.tiling_mode;
+ return 0;
+}
+
+static void *i915_bo_map(struct bo *bo, struct map_info *data, size_t plane, int prot)
+{
+ int ret;
+ void *addr;
+ struct drm_i915_gem_set_domain set_domain;
+
+ memset(&set_domain, 0, sizeof(set_domain));
+ set_domain.handle = bo->handles[0].u32;
+ if (bo->tiling == I915_TILING_NONE) {
+ struct drm_i915_gem_mmap gem_map;
+ memset(&gem_map, 0, sizeof(gem_map));
+
+ gem_map.handle = bo->handles[0].u32;
+ gem_map.offset = 0;
+ gem_map.size = bo->total_size;
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_MMAP, &gem_map);
+ if (ret) {
+ fprintf(stderr, "drv: DRM_IOCTL_I915_GEM_MMAP failed\n");
+ return MAP_FAILED;
+ }
+
+ addr = (void *)(uintptr_t)gem_map.addr_ptr;
+ set_domain.read_domains = I915_GEM_DOMAIN_CPU;
+ set_domain.write_domain = I915_GEM_DOMAIN_CPU;
+
+ } else {
+ struct drm_i915_gem_mmap_gtt gem_map;
+ memset(&gem_map, 0, sizeof(gem_map));
+
+ gem_map.handle = bo->handles[0].u32;
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &gem_map);
+ if (ret) {
+ fprintf(stderr, "drv: DRM_IOCTL_I915_GEM_MMAP_GTT failed\n");
+ return MAP_FAILED;
+ }
+
+ addr = mmap(0, bo->total_size, prot, MAP_SHARED, bo->drv->fd, gem_map.offset);
+ set_domain.read_domains = I915_GEM_DOMAIN_GTT;
+ set_domain.write_domain = I915_GEM_DOMAIN_GTT;
+ }
+
+ if (addr == MAP_FAILED) {
+ fprintf(stderr, "drv: i915 GEM mmap failed\n");
+ return addr;
+ }
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
+ if (ret) {
+ fprintf(stderr, "drv: DRM_IOCTL_I915_GEM_SET_DOMAIN failed\n");
+ return MAP_FAILED;
+ }
+
+ data->length = bo->total_size;
+ return addr;
+}
+
+static int i915_bo_unmap(struct bo *bo, struct map_info *data)
+{
+ struct i915_device *i915 = bo->drv->priv;
+ if (!i915->has_llc && bo->tiling == I915_TILING_NONE)
+ i915_clflush(data->addr, data->length);
+
+ return munmap(data->addr, data->length);
+}
+
+static uint32_t i915_resolve_format(uint32_t format, uint64_t usage)
+{
+ switch (format) {
+ case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
+ /* KBL camera subsystem requires NV12. */
+ if (usage & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE))
+ return DRM_FORMAT_NV12;
+ /*HACK: See b/28671744 */
+ return DRM_FORMAT_XBGR8888;
+ case DRM_FORMAT_FLEX_YCbCr_420_888:
+ /* KBL camera subsystem requires NV12. */
+ if (usage & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE))
+ return DRM_FORMAT_NV12;
+ return DRM_FORMAT_YVU420;
+ default:
+ return format;
+ }
+}
+
+struct backend backend_i915 = {
+ .name = "i915",
+ .init = i915_init,
+ .close = i915_close,
+ .bo_create = i915_bo_create,
+ .bo_destroy = drv_gem_bo_destroy,
+ .bo_import = i915_bo_import,
+ .bo_map = i915_bo_map,
+ .bo_unmap = i915_bo_unmap,
+ .resolve_format = i915_resolve_format,
+};
+
+#endif
diff --git a/chromium/third_party/minigbm/src/marvell.c b/chromium/third_party/minigbm/src/marvell.c
new file mode 100644
index 00000000000..8114ac7d7ae
--- /dev/null
+++ b/chromium/third_party/minigbm/src/marvell.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifdef DRV_MARVELL
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 };
+
+static int marvell_init(struct driver *drv)
+{
+ int ret;
+ ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+ &LINEAR_METADATA, BO_USE_RENDER_MASK);
+ if (ret)
+ return ret;
+
+ return drv_add_linear_combinations(drv, render_target_formats,
+ ARRAY_SIZE(render_target_formats));
+}
+
+struct backend backend_marvell = {
+ .name = "marvell",
+ .init = marvell_init,
+ .bo_create = drv_dumb_bo_create,
+ .bo_destroy = drv_dumb_bo_destroy,
+ .bo_import = drv_prime_bo_import,
+ .bo_map = drv_dumb_bo_map,
+};
+
+#endif
diff --git a/chromium/third_party/minigbm/src/mediatek.c b/chromium/third_party/minigbm/src/mediatek.c
new file mode 100644
index 00000000000..a4879d9d623
--- /dev/null
+++ b/chromium/third_party/minigbm/src/mediatek.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifdef DRV_MEDIATEK
+
+// clang-format off
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <xf86drm.h>
+#include <mediatek_drm.h>
+// clang-format on
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+struct mediatek_private_map_data {
+ void *cached_addr;
+ void *gem_addr;
+};
+
+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 mediatek_init(struct driver *drv)
+{
+ int ret;
+ ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+ &LINEAR_METADATA, BO_USE_RENDER_MASK);
+ if (ret)
+ return ret;
+
+ ret = drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats),
+ &LINEAR_METADATA, BO_USE_TEXTURE_MASK);
+ if (ret)
+ return ret;
+
+ return drv_modify_linear_combinations(drv);
+}
+
+static int mediatek_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+ uint32_t flags)
+{
+ int ret;
+ size_t plane;
+ uint32_t stride;
+ struct drm_mtk_gem_create gem_create;
+
+ /*
+ * Since the ARM L1 cache line size is 64 bytes, align to that as a
+ * performance optimization.
+ */
+ stride = drv_stride_from_format(format, width, 0);
+ stride = ALIGN(stride, 64);
+ drv_bo_from_format(bo, stride, height, format);
+
+ memset(&gem_create, 0, sizeof(gem_create));
+ gem_create.size = bo->total_size;
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MTK_GEM_CREATE, &gem_create);
+ if (ret) {
+ fprintf(stderr, "drv: DRM_IOCTL_MTK_GEM_CREATE failed (size=%llu)\n",
+ gem_create.size);
+ return ret;
+ }
+
+ for (plane = 0; plane < bo->num_planes; plane++)
+ bo->handles[plane].u32 = gem_create.handle;
+
+ return 0;
+}
+
+static void *mediatek_bo_map(struct bo *bo, struct map_info *data, size_t plane, int prot)
+{
+ int ret;
+ struct drm_mtk_gem_map_off gem_map;
+ struct mediatek_private_map_data *priv;
+
+ memset(&gem_map, 0, sizeof(gem_map));
+ gem_map.handle = bo->handles[0].u32;
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MTK_GEM_MAP_OFFSET, &gem_map);
+ if (ret) {
+ fprintf(stderr, "drv: DRM_IOCTL_MTK_GEM_MAP_OFFSET failed\n");
+ return MAP_FAILED;
+ }
+
+ void *addr = mmap(0, bo->total_size, prot, MAP_SHARED, bo->drv->fd, gem_map.offset);
+
+ data->length = bo->total_size;
+
+ if (bo->flags & BO_USE_RENDERSCRIPT) {
+ priv = calloc(1, sizeof(*priv));
+ priv->cached_addr = calloc(1, bo->total_size);
+ priv->gem_addr = addr;
+ memcpy(priv->cached_addr, priv->gem_addr, bo->total_size);
+ data->priv = priv;
+ addr = priv->cached_addr;
+ }
+
+ return addr;
+}
+
+static int mediatek_bo_unmap(struct bo *bo, struct map_info *data)
+{
+ if (data->priv) {
+ struct mediatek_private_map_data *priv = data->priv;
+ memcpy(priv->gem_addr, priv->cached_addr, bo->total_size);
+ data->addr = priv->gem_addr;
+ free(priv->cached_addr);
+ free(priv);
+ data->priv = NULL;
+ }
+
+ return munmap(data->addr, data->length);
+}
+
+static uint32_t mediatek_resolve_format(uint32_t format, uint64_t usage)
+{
+ 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;
+ }
+}
+
+struct backend backend_mediatek = {
+ .name = "mediatek",
+ .init = mediatek_init,
+ .bo_create = mediatek_bo_create,
+ .bo_destroy = drv_gem_bo_destroy,
+ .bo_import = drv_prime_bo_import,
+ .bo_map = mediatek_bo_map,
+ .bo_unmap = mediatek_bo_unmap,
+ .resolve_format = mediatek_resolve_format,
+};
+
+#endif
diff --git a/chromium/third_party/minigbm/src/nouveau.c b/chromium/third_party/minigbm/src/nouveau.c
new file mode 100644
index 00000000000..7cdab3a040d
--- /dev/null
+++ b/chromium/third_party/minigbm/src/nouveau.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2016 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 };
+
+static int nouveau_init(struct driver *drv)
+{
+ int ret;
+ ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+ &LINEAR_METADATA, BO_USE_RENDER_MASK);
+ if (ret)
+ return ret;
+
+ return drv_modify_linear_combinations(drv);
+}
+
+struct backend backend_nouveau = {
+ .name = "nouveau",
+ .init = nouveau_init,
+ .bo_create = drv_dumb_bo_create,
+ .bo_destroy = drv_dumb_bo_destroy,
+ .bo_import = drv_prime_bo_import,
+ .bo_map = drv_dumb_bo_map,
+};
diff --git a/chromium/third_party/minigbm/src/presubmit.sh b/chromium/third_party/minigbm/src/presubmit.sh
new file mode 100755
index 00000000000..6d55f2a5e70
--- /dev/null
+++ b/chromium/third_party/minigbm/src/presubmit.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+# 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.
+find \
+ '(' -name '*.[ch]' -or -name '*.cc' ')' \
+ -not -name 'gbm.h' \
+ -exec clang-format -style=file -i {} +
diff --git a/chromium/third_party/minigbm/src/radeon.c b/chromium/third_party/minigbm/src/radeon.c
new file mode 100644
index 00000000000..baf42ed994f
--- /dev/null
+++ b/chromium/third_party/minigbm/src/radeon.c
@@ -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.
+ */
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 };
+
+static int radeon_init(struct driver *drv)
+{
+ int ret;
+ ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+ &LINEAR_METADATA, BO_USE_RENDER_MASK);
+ if (ret)
+ return ret;
+
+ return drv_modify_linear_combinations(drv);
+}
+
+struct backend backend_radeon = {
+ .name = "radeon",
+ .init = radeon_init,
+ .bo_create = drv_dumb_bo_create,
+ .bo_destroy = drv_dumb_bo_destroy,
+ .bo_import = drv_prime_bo_import,
+ .bo_map = drv_dumb_bo_map,
+};
diff --git a/chromium/third_party/minigbm/src/rockchip.c b/chromium/third_party/minigbm/src/rockchip.c
new file mode 100644
index 00000000000..fbc9ed5c0de
--- /dev/null
+++ b/chromium/third_party/minigbm/src/rockchip.c
@@ -0,0 +1,308 @@
+/*
+ * 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_ROCKCHIP
+
+#include <errno.h>
+#include <rockchip_drm.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <xf86drm.h>
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+struct rockchip_private_map_data {
+ void *cached_addr;
+ void *gem_addr;
+};
+
+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_NV12,
+ DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID };
+
+static int afbc_bo_from_format(struct bo *bo, uint32_t width, uint32_t height, uint32_t format)
+{
+ /* We've restricted ourselves to four bytes per pixel. */
+ const uint32_t pixel_size = 4;
+
+ const uint32_t clump_width = 4;
+ const uint32_t clump_height = 4;
+
+#define AFBC_NARROW 1
+#if AFBC_NARROW == 1
+ const uint32_t block_width = 4 * clump_width;
+ const uint32_t block_height = 4 * clump_height;
+#else
+ const uint32_t block_width = 8 * clump_width;
+ const uint32_t block_height = 2 * clump_height;
+#endif
+
+ const uint32_t header_block_size = 16;
+ const uint32_t body_block_size = block_width * block_height * pixel_size;
+ const uint32_t width_in_blocks = DIV_ROUND_UP(width, block_width);
+ const uint32_t height_in_blocks = DIV_ROUND_UP(height, block_height);
+ const uint32_t total_blocks = width_in_blocks * height_in_blocks;
+
+ const uint32_t header_plane_size = total_blocks * header_block_size;
+ const uint32_t body_plane_size = total_blocks * body_block_size;
+
+ /* GPU requires 64 bytes, but EGL import code expects 1024 byte
+ * alignement for the body plane. */
+ const uint32_t body_plane_alignment = 1024;
+
+ const uint32_t body_plane_offset = ALIGN(header_plane_size, body_plane_alignment);
+ const uint32_t total_size = body_plane_offset + body_plane_size;
+
+ bo->strides[0] = width_in_blocks * block_width * pixel_size;
+ bo->sizes[0] = total_size;
+ bo->offsets[0] = 0;
+
+ bo->total_size = total_size;
+
+ bo->format_modifiers[0] = DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC;
+
+ return 0;
+}
+
+static int rockchip_add_kms_item(struct driver *drv, const struct kms_item *item)
+{
+ int ret;
+ uint32_t i, j;
+ uint64_t flags;
+ struct combination *combo;
+ struct format_metadata metadata;
+
+ for (i = 0; i < drv->backend->combos.size; i++) {
+ combo = &drv->backend->combos.data[i];
+ if (combo->format == item->format) {
+ if (item->modifier == DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC) {
+ flags = BO_USE_RENDERING | BO_USE_SCANOUT | BO_USE_TEXTURE;
+ metadata.modifier = item->modifier;
+ metadata.tiling = 0;
+ metadata.priority = 2;
+
+ for (j = 0; j < ARRAY_SIZE(texture_source_formats); j++) {
+ if (item->format == texture_source_formats[j])
+ flags &= ~BO_USE_RENDERING;
+ }
+
+ ret = drv_add_combination(drv, item[i].format, &metadata, flags);
+ if (ret)
+ return ret;
+ } else {
+ combo->usage |= item->usage;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int rockchip_init(struct driver *drv)
+{
+ int ret;
+ uint32_t i, num_items;
+ struct kms_item *items;
+ struct format_metadata metadata;
+
+ metadata.tiling = 0;
+ metadata.priority = 1;
+ metadata.modifier = DRM_FORMAT_MOD_NONE;
+
+ ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+ &metadata, BO_USE_RENDER_MASK);
+ if (ret)
+ return ret;
+
+ ret = drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats),
+ &metadata, BO_USE_TEXTURE_MASK);
+ if (ret)
+ return ret;
+
+ drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT);
+ drv_modify_combination(drv, DRM_FORMAT_ARGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT);
+
+ items = drv_query_kms(drv, &num_items);
+ if (!items || !num_items)
+ return 0;
+
+ for (i = 0; i < num_items; i++) {
+ ret = rockchip_add_kms_item(drv, &items[i]);
+ if (ret) {
+ free(items);
+ return ret;
+ }
+ }
+
+ free(items);
+ return 0;
+}
+
+static bool has_modifier(const uint64_t *list, uint32_t count, uint64_t modifier)
+{
+ uint32_t i;
+
+ for (i = 0; i < count; i++)
+ if (list[i] == modifier)
+ return true;
+
+ return false;
+}
+
+static int rockchip_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint32_t height,
+ uint32_t format, const uint64_t *modifiers,
+ uint32_t count)
+{
+ int ret;
+ size_t plane;
+ struct drm_rockchip_gem_create gem_create;
+
+ if (format == DRM_FORMAT_NV12) {
+ uint32_t w_mbs = DIV_ROUND_UP(ALIGN(width, 16), 16);
+ uint32_t h_mbs = DIV_ROUND_UP(ALIGN(height, 16), 16);
+
+ uint32_t aligned_width = w_mbs * 16;
+ uint32_t aligned_height = DIV_ROUND_UP(h_mbs * 16 * 3, 2);
+
+ drv_bo_from_format(bo, aligned_width, height, format);
+ bo->total_size = bo->strides[0] * aligned_height + w_mbs * h_mbs * 128;
+ } else if (width <= 2560 &&
+ has_modifier(modifiers, count, DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC)) {
+ /* If the caller has decided they can use AFBC, always
+ * pick that */
+ afbc_bo_from_format(bo, width, height, format);
+ } else {
+ if (!has_modifier(modifiers, count, DRM_FORMAT_MOD_NONE)) {
+ errno = EINVAL;
+ fprintf(stderr, "no usable modifier found\n");
+ return -1;
+ }
+
+ uint32_t stride;
+ /*
+ * Since the ARM L1 cache line size is 64 bytes, align to that
+ * as a performance optimization. For YV12, the Mali cmem allocator
+ * requires that chroma planes are aligned to 64-bytes, so align the
+ * luma plane to 128 bytes.
+ */
+ stride = drv_stride_from_format(format, width, 0);
+ if (format == DRM_FORMAT_YVU420 || format == DRM_FORMAT_YVU420_ANDROID)
+ stride = ALIGN(stride, 128);
+ else
+ stride = ALIGN(stride, 64);
+
+ drv_bo_from_format(bo, stride, height, format);
+ }
+
+ memset(&gem_create, 0, sizeof(gem_create));
+ gem_create.size = bo->total_size;
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_ROCKCHIP_GEM_CREATE, &gem_create);
+
+ if (ret) {
+ fprintf(stderr, "drv: DRM_IOCTL_ROCKCHIP_GEM_CREATE failed (size=%llu)\n",
+ gem_create.size);
+ return ret;
+ }
+
+ for (plane = 0; plane < bo->num_planes; plane++)
+ bo->handles[plane].u32 = gem_create.handle;
+
+ return 0;
+}
+
+static int rockchip_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+ uint32_t flags)
+{
+ uint64_t modifiers[] = { DRM_FORMAT_MOD_NONE };
+
+ return rockchip_bo_create_with_modifiers(bo, width, height, format, modifiers,
+ ARRAY_SIZE(modifiers));
+}
+
+static void *rockchip_bo_map(struct bo *bo, struct map_info *data, size_t plane, int prot)
+{
+ int ret;
+ struct drm_rockchip_gem_map_off gem_map;
+ struct rockchip_private_map_data *priv;
+
+ /* We can only map buffers created with SW access flags, which should
+ * have no modifiers (ie, not AFBC). */
+ if (bo->format_modifiers[0] == DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC)
+ return MAP_FAILED;
+
+ memset(&gem_map, 0, sizeof(gem_map));
+ gem_map.handle = bo->handles[0].u32;
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_ROCKCHIP_GEM_MAP_OFFSET, &gem_map);
+ if (ret) {
+ fprintf(stderr, "drv: DRM_IOCTL_ROCKCHIP_GEM_MAP_OFFSET failed\n");
+ return MAP_FAILED;
+ }
+
+ void *addr = mmap(0, bo->total_size, prot, MAP_SHARED, bo->drv->fd, gem_map.offset);
+
+ data->length = bo->total_size;
+
+ if (bo->flags & BO_USE_RENDERSCRIPT) {
+ priv = calloc(1, sizeof(*priv));
+ priv->cached_addr = calloc(1, bo->total_size);
+ priv->gem_addr = addr;
+ memcpy(priv->cached_addr, priv->gem_addr, bo->total_size);
+ data->priv = priv;
+ addr = priv->cached_addr;
+ }
+
+ return addr;
+}
+
+static int rockchip_bo_unmap(struct bo *bo, struct map_info *data)
+{
+ if (data->priv) {
+ struct rockchip_private_map_data *priv = data->priv;
+ memcpy(priv->gem_addr, priv->cached_addr, bo->total_size);
+ data->addr = priv->gem_addr;
+ free(priv->cached_addr);
+ free(priv);
+ data->priv = NULL;
+ }
+
+ return munmap(data->addr, data->length);
+}
+
+static uint32_t rockchip_resolve_format(uint32_t format, uint64_t usage)
+{
+ 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_NV12;
+ default:
+ return format;
+ }
+}
+
+struct backend backend_rockchip = {
+ .name = "rockchip",
+ .init = rockchip_init,
+ .bo_create = rockchip_bo_create,
+ .bo_create_with_modifiers = rockchip_bo_create_with_modifiers,
+ .bo_destroy = drv_gem_bo_destroy,
+ .bo_import = drv_prime_bo_import,
+ .bo_map = rockchip_bo_map,
+ .bo_unmap = rockchip_bo_unmap,
+ .resolve_format = rockchip_resolve_format,
+};
+
+#endif
diff --git a/chromium/third_party/minigbm/src/tegra.c b/chromium/third_party/minigbm/src/tegra.c
new file mode 100644
index 00000000000..7ddeb96873c
--- /dev/null
+++ b/chromium/third_party/minigbm/src/tegra.c
@@ -0,0 +1,359 @@
+/*
+ * Copyright 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifdef DRV_TEGRA
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <tegra_drm.h>
+#include <xf86drm.h>
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+/*
+ * GOB (Group Of Bytes) is the basic unit of the blocklinear layout.
+ * GOBs are arranged to blocks, where the height of the block (measured
+ * in GOBs) is configurable.
+ */
+#define NV_BLOCKLINEAR_GOB_HEIGHT 8
+#define NV_BLOCKLINEAR_GOB_WIDTH 64
+#define NV_DEFAULT_BLOCK_HEIGHT_LOG2 4
+#define NV_PREFERRED_PAGE_SIZE (128 * 1024)
+
+// clang-format off
+enum nv_mem_kind
+{
+ NV_MEM_KIND_PITCH = 0,
+ NV_MEM_KIND_C32_2CRA = 0xdb,
+ NV_MEM_KIND_GENERIC_16Bx2 = 0xfe,
+};
+
+enum tegra_map_type {
+ TEGRA_READ_TILED_BUFFER = 0,
+ TEGRA_WRITE_TILED_BUFFER = 1,
+};
+// clang-format on
+
+struct tegra_private_map_data {
+ void *tiled;
+ void *untiled;
+ int prot;
+};
+
+static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 };
+
+static int compute_block_height_log2(int height)
+{
+ int block_height_log2 = NV_DEFAULT_BLOCK_HEIGHT_LOG2;
+
+ if (block_height_log2 > 0) {
+ /* Shrink, if a smaller block height could cover the whole
+ * surface height. */
+ int proposed = NV_BLOCKLINEAR_GOB_HEIGHT << (block_height_log2 - 1);
+ while (proposed >= height) {
+ block_height_log2--;
+ if (block_height_log2 == 0)
+ break;
+ proposed /= 2;
+ }
+ }
+ return block_height_log2;
+}
+
+static void compute_layout_blocklinear(int width, int height, int format, enum nv_mem_kind *kind,
+ uint32_t *block_height_log2, uint32_t *stride,
+ uint32_t *size)
+{
+ int pitch = drv_stride_from_format(format, width, 0);
+
+ /* Align to blocklinear blocks. */
+ pitch = ALIGN(pitch, NV_BLOCKLINEAR_GOB_WIDTH);
+
+ /* Compute padded height. */
+ *block_height_log2 = compute_block_height_log2(height);
+ int block_height = 1 << *block_height_log2;
+ int padded_height = ALIGN(height, NV_BLOCKLINEAR_GOB_HEIGHT * block_height);
+
+ int bytes = pitch * padded_height;
+
+ /* Pad the allocation to the preferred page size.
+ * This will reduce the required page table size (see discussion in NV
+ * bug 1321091), and also acts as a WAR for NV bug 1325421.
+ */
+ bytes = ALIGN(bytes, NV_PREFERRED_PAGE_SIZE);
+
+ *kind = NV_MEM_KIND_C32_2CRA;
+ *stride = pitch;
+ *size = bytes;
+}
+
+static void compute_layout_linear(int width, int height, int format, uint32_t *stride,
+ uint32_t *size)
+{
+ *stride = ALIGN(drv_stride_from_format(format, width, 0), 64);
+ *size = *stride * height;
+}
+
+static void transfer_tile(struct bo *bo, uint8_t *tiled, uint8_t *untiled, enum tegra_map_type type,
+ uint32_t bytes_per_pixel, uint32_t gob_top, uint32_t gob_left,
+ uint32_t gob_size_pixels, uint8_t *tiled_last)
+{
+ uint8_t *tmp;
+ uint32_t x, y, k;
+ for (k = 0; k < gob_size_pixels; k++) {
+ /*
+ * Given the kth pixel starting from the tile specified by
+ * gob_top and gob_left, unswizzle to get the standard (x, y)
+ * representation.
+ */
+ x = gob_left + (((k >> 3) & 8) | ((k >> 1) & 4) | (k & 3));
+ y = gob_top + ((k >> 7 << 3) | ((k >> 3) & 6) | ((k >> 2) & 1));
+
+ if (tiled >= tiled_last)
+ return;
+
+ if (x >= bo->width || y >= bo->height) {
+ tiled += bytes_per_pixel;
+ continue;
+ }
+
+ tmp = untiled + y * bo->strides[0] + x * bytes_per_pixel;
+
+ if (type == TEGRA_READ_TILED_BUFFER)
+ memcpy(tmp, tiled, bytes_per_pixel);
+ else if (type == TEGRA_WRITE_TILED_BUFFER)
+ memcpy(tiled, tmp, bytes_per_pixel);
+
+ /* Move on to next pixel. */
+ tiled += bytes_per_pixel;
+ }
+}
+
+static void transfer_tiled_memory(struct bo *bo, uint8_t *tiled, uint8_t *untiled,
+ enum tegra_map_type type)
+{
+ uint32_t gob_width, gob_height, gob_size_bytes, gob_size_pixels, gob_count_x, gob_count_y,
+ gob_top, gob_left;
+ uint32_t i, j, offset;
+ uint8_t *tmp, *tiled_last;
+ uint32_t bytes_per_pixel = drv_stride_from_format(bo->format, 1, 0);
+
+ /*
+ * The blocklinear format consists of 8*(2^n) x 64 byte sized tiles,
+ * where 0 <= n <= 4.
+ */
+ gob_width = DIV_ROUND_UP(NV_BLOCKLINEAR_GOB_WIDTH, bytes_per_pixel);
+ gob_height = NV_BLOCKLINEAR_GOB_HEIGHT * (1 << NV_DEFAULT_BLOCK_HEIGHT_LOG2);
+ /* Calculate the height from maximum possible gob height */
+ while (gob_height > NV_BLOCKLINEAR_GOB_HEIGHT && gob_height >= 2 * bo->height)
+ gob_height /= 2;
+
+ gob_size_bytes = gob_height * NV_BLOCKLINEAR_GOB_WIDTH;
+ gob_size_pixels = gob_height * gob_width;
+
+ gob_count_x = DIV_ROUND_UP(bo->strides[0], NV_BLOCKLINEAR_GOB_WIDTH);
+ gob_count_y = DIV_ROUND_UP(bo->height, gob_height);
+
+ tiled_last = tiled + bo->total_size;
+
+ offset = 0;
+ for (j = 0; j < gob_count_y; j++) {
+ gob_top = j * gob_height;
+ for (i = 0; i < gob_count_x; i++) {
+ tmp = tiled + offset;
+ gob_left = i * gob_width;
+
+ transfer_tile(bo, tmp, untiled, type, bytes_per_pixel, gob_top, gob_left,
+ gob_size_pixels, tiled_last);
+
+ offset += gob_size_bytes;
+ }
+ }
+}
+
+static int tegra_init(struct driver *drv)
+{
+ int ret;
+ struct format_metadata metadata;
+ uint64_t flags = BO_USE_RENDER_MASK;
+
+ metadata.tiling = NV_MEM_KIND_PITCH;
+ metadata.priority = 1;
+ metadata.modifier = DRM_FORMAT_MOD_NONE;
+
+ ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+ &metadata, flags);
+ if (ret)
+ return ret;
+
+ drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT);
+ drv_modify_combination(drv, DRM_FORMAT_ARGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT);
+
+ flags &= ~BO_USE_SW_WRITE_OFTEN;
+ flags &= ~BO_USE_SW_READ_OFTEN;
+ flags &= ~BO_USE_LINEAR;
+
+ metadata.tiling = NV_MEM_KIND_C32_2CRA;
+ metadata.priority = 2;
+
+ ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+ &metadata, flags);
+ if (ret)
+ return ret;
+
+ drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_SCANOUT);
+ drv_modify_combination(drv, DRM_FORMAT_ARGB8888, &metadata, BO_USE_SCANOUT);
+ return 0;
+}
+
+static int tegra_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+ uint32_t flags)
+{
+ uint32_t size, stride, block_height_log2 = 0;
+ enum nv_mem_kind kind = NV_MEM_KIND_PITCH;
+ struct drm_tegra_gem_create gem_create;
+ int ret;
+
+ if (flags & (BO_USE_CURSOR | BO_USE_LINEAR | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN))
+ compute_layout_linear(width, height, format, &stride, &size);
+ else
+ compute_layout_blocklinear(width, height, format, &kind, &block_height_log2,
+ &stride, &size);
+
+ memset(&gem_create, 0, sizeof(gem_create));
+ gem_create.size = size;
+ gem_create.flags = 0;
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_TEGRA_GEM_CREATE, &gem_create);
+ if (ret) {
+ fprintf(stderr, "drv: DRM_IOCTL_TEGRA_GEM_CREATE failed (size=%zu)\n", size);
+ return ret;
+ }
+
+ bo->handles[0].u32 = gem_create.handle;
+ bo->offsets[0] = 0;
+ bo->total_size = bo->sizes[0] = size;
+ bo->strides[0] = stride;
+
+ if (kind != NV_MEM_KIND_PITCH) {
+ struct drm_tegra_gem_set_tiling gem_tile;
+
+ memset(&gem_tile, 0, sizeof(gem_tile));
+ gem_tile.handle = bo->handles[0].u32;
+ gem_tile.mode = DRM_TEGRA_GEM_TILING_MODE_BLOCK;
+ gem_tile.value = block_height_log2;
+
+ ret = drmCommandWriteRead(bo->drv->fd, DRM_TEGRA_GEM_SET_TILING, &gem_tile,
+ sizeof(gem_tile));
+ if (ret < 0) {
+ drv_gem_bo_destroy(bo);
+ return ret;
+ }
+
+ /* Encode blocklinear parameters for EGLImage creation. */
+ bo->tiling = (kind & 0xff) | ((block_height_log2 & 0xf) << 8);
+ bo->format_modifiers[0] = fourcc_mod_code(NV, bo->tiling);
+ }
+
+ return 0;
+}
+
+static void *tegra_bo_map(struct bo *bo, struct map_info *data, size_t plane, int prot)
+{
+ int ret;
+ struct drm_tegra_gem_mmap gem_map;
+ struct tegra_private_map_data *priv;
+
+ memset(&gem_map, 0, sizeof(gem_map));
+ gem_map.handle = bo->handles[0].u32;
+
+ ret = drmCommandWriteRead(bo->drv->fd, DRM_TEGRA_GEM_MMAP, &gem_map, sizeof(gem_map));
+ if (ret < 0) {
+ fprintf(stderr, "drv: DRM_TEGRA_GEM_MMAP failed\n");
+ return MAP_FAILED;
+ }
+
+ void *addr = mmap(0, bo->total_size, prot, MAP_SHARED, bo->drv->fd, gem_map.offset);
+ data->length = bo->total_size;
+ if ((bo->tiling & 0xFF) == NV_MEM_KIND_C32_2CRA && addr != MAP_FAILED) {
+ priv = calloc(1, sizeof(*priv));
+ priv->untiled = calloc(1, bo->total_size);
+ priv->tiled = addr;
+ priv->prot = prot;
+ data->priv = priv;
+ transfer_tiled_memory(bo, priv->tiled, priv->untiled, TEGRA_READ_TILED_BUFFER);
+ addr = priv->untiled;
+ }
+
+ return addr;
+}
+
+static int tegra_bo_unmap(struct bo *bo, struct map_info *data)
+{
+ if (data->priv) {
+ struct tegra_private_map_data *priv = data->priv;
+ if (priv->prot & PROT_WRITE)
+ transfer_tiled_memory(bo, priv->tiled, priv->untiled,
+ TEGRA_WRITE_TILED_BUFFER);
+ data->addr = priv->tiled;
+ free(priv->untiled);
+ free(priv);
+ data->priv = NULL;
+ }
+
+ return munmap(data->addr, data->length);
+}
+
+static int tegra_bo_import(struct bo *bo, struct drv_import_fd_data *data)
+{
+ int ret;
+ struct drm_tegra_gem_get_tiling gem_get_tiling;
+
+ ret = drv_prime_bo_import(bo, data);
+ if (ret)
+ return ret;
+
+ /* TODO(gsingh): export modifiers and get rid of backdoor tiling. */
+ memset(&gem_get_tiling, 0, sizeof(gem_get_tiling));
+ gem_get_tiling.handle = bo->handles[0].u32;
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_TEGRA_GEM_GET_TILING, &gem_get_tiling);
+ if (ret) {
+ drv_gem_bo_destroy(bo);
+ return ret;
+ }
+
+ /* NOTE(djmk): we only know about one tiled format, so if our drmIoctl call tells us we are
+ tiled, assume it is this format (NV_MEM_KIND_C32_2CRA) otherwise linear (KIND_PITCH). */
+ if (gem_get_tiling.mode == DRM_TEGRA_GEM_TILING_MODE_PITCH) {
+ bo->tiling = NV_MEM_KIND_PITCH;
+ } else if (gem_get_tiling.mode == DRM_TEGRA_GEM_TILING_MODE_BLOCK) {
+ bo->tiling = NV_MEM_KIND_C32_2CRA;
+ } else {
+ fprintf(stderr, "tegra_bo_import: unknown tile format %d", gem_get_tiling.mode);
+ drv_gem_bo_destroy(bo);
+ assert(0);
+ }
+
+ bo->format_modifiers[0] = fourcc_mod_code(NV, bo->tiling);
+ return 0;
+}
+
+struct backend backend_tegra = {
+ .name = "tegra",
+ .init = tegra_init,
+ .bo_create = tegra_bo_create,
+ .bo_destroy = drv_gem_bo_destroy,
+ .bo_import = tegra_bo_import,
+ .bo_map = tegra_bo_map,
+ .bo_unmap = tegra_bo_unmap,
+};
+
+#endif
diff --git a/chromium/third_party/minigbm/src/udl.c b/chromium/third_party/minigbm/src/udl.c
new file mode 100644
index 00000000000..eb15fbeb461
--- /dev/null
+++ b/chromium/third_party/minigbm/src/udl.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 };
+
+static int udl_init(struct driver *drv)
+{
+ int ret;
+ ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+ &LINEAR_METADATA, BO_USE_RENDER_MASK);
+ if (ret)
+ return ret;
+
+ return drv_modify_linear_combinations(drv);
+}
+
+struct backend backend_udl = {
+ .name = "udl",
+ .init = udl_init,
+ .bo_create = drv_dumb_bo_create,
+ .bo_destroy = drv_dumb_bo_destroy,
+ .bo_import = drv_prime_bo_import,
+ .bo_map = drv_dumb_bo_map,
+};
diff --git a/chromium/third_party/minigbm/src/util.h b/chromium/third_party/minigbm/src/util.h
new file mode 100644
index 00000000000..fd61d9b4b61
--- /dev/null
+++ b/chromium/third_party/minigbm/src/util.h
@@ -0,0 +1,16 @@
+/*
+ * 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.
+ */
+
+#ifndef UTIL_H
+#define UTIL_H
+
+#define MAX(A, B) ((A) > (B) ? (A) : (B))
+#define ARRAY_SIZE(A) (sizeof(A) / sizeof(*(A)))
+#define PUBLIC __attribute__((visibility("default")))
+#define ALIGN(A, B) (((A) + (B)-1) / (B) * (B))
+#define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d))
+
+#endif
diff --git a/chromium/third_party/minigbm/src/vc4.c b/chromium/third_party/minigbm/src/vc4.c
new file mode 100644
index 00000000000..c797bd9529c
--- /dev/null
+++ b/chromium/third_party/minigbm/src/vc4.c
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+#ifdef DRV_VC4
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <vc4_drm.h>
+#include <xf86drm.h>
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_RGB565,
+ DRM_FORMAT_XRGB8888 };
+
+static int vc4_init(struct driver *drv)
+{
+ int ret;
+ ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+ &LINEAR_METADATA, BO_USE_RENDER_MASK);
+ if (ret)
+ return ret;
+
+ return drv_modify_linear_combinations(drv);
+}
+
+static int vc4_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+ uint32_t flags)
+{
+ int ret;
+ size_t plane;
+ uint32_t stride;
+ struct drm_vc4_create_bo bo_create;
+
+ /*
+ * Since the ARM L1 cache line size is 64 bytes, align to that as a
+ * performance optimization.
+ */
+ stride = drv_stride_from_format(format, width, 0);
+ stride = ALIGN(stride, 64);
+ drv_bo_from_format(bo, stride, height, format);
+
+ memset(&bo_create, 0, sizeof(bo_create));
+ bo_create.size = bo->total_size;
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VC4_CREATE_BO, &bo_create);
+ if (ret) {
+ fprintf(stderr, "drv: DRM_IOCTL_VC4_GEM_CREATE failed (size=%zu)\n",
+ bo->total_size);
+ return ret;
+ }
+
+ for (plane = 0; plane < bo->num_planes; plane++)
+ bo->handles[plane].u32 = bo_create.handle;
+
+ return 0;
+}
+
+static void *vc4_bo_map(struct bo *bo, struct map_info *data, size_t plane, int prot)
+{
+ int ret;
+ struct drm_vc4_mmap_bo bo_map;
+
+ memset(&bo_map, 0, sizeof(bo_map));
+ bo_map.handle = bo->handles[0].u32;
+
+ ret = drmCommandWriteRead(bo->drv->fd, DRM_VC4_MMAP_BO, &bo_map, sizeof(bo_map));
+ if (ret) {
+ fprintf(stderr, "drv: DRM_VC4_MMAP_BO failed\n");
+ return MAP_FAILED;
+ }
+
+ data->length = bo->total_size;
+ return mmap(0, bo->total_size, prot, MAP_SHARED, bo->drv->fd, bo_map.offset);
+}
+
+struct backend backend_vc4 = {
+ .name = "vc4",
+ .init = vc4_init,
+ .bo_create = vc4_bo_create,
+ .bo_import = drv_prime_bo_import,
+ .bo_destroy = drv_gem_bo_destroy,
+ .bo_map = vc4_bo_map,
+};
+
+#endif
diff --git a/chromium/third_party/minigbm/src/vgem.c b/chromium/third_party/minigbm/src/vgem.c
new file mode 100644
index 00000000000..4e6eefb7375
--- /dev/null
+++ b/chromium/third_party/minigbm/src/vgem.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2016 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+#define MESA_LLVMPIPE_TILE_ORDER 6
+#define MESA_LLVMPIPE_TILE_SIZE (1 << MESA_LLVMPIPE_TILE_ORDER)
+
+static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888,
+ DRM_FORMAT_XRGB8888 };
+
+static const uint32_t texture_source_formats[] = { DRM_FORMAT_R8, DRM_FORMAT_YVU420,
+ DRM_FORMAT_YVU420_ANDROID };
+
+static int vgem_init(struct driver *drv)
+{
+ int ret;
+ ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+ &LINEAR_METADATA, BO_USE_RENDER_MASK);
+ if (ret)
+ return ret;
+
+ ret = drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats),
+ &LINEAR_METADATA, BO_USE_TEXTURE_MASK);
+ if (ret)
+ return ret;
+
+ return drv_modify_linear_combinations(drv);
+}
+
+static int vgem_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+ uint32_t 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, flags);
+}
+
+static uint32_t vgem_resolve_format(uint32_t format, uint64_t usage)
+{
+ 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;
+ }
+}
+
+struct backend backend_vgem = {
+ .name = "vgem",
+ .init = vgem_init,
+ .bo_create = vgem_bo_create,
+ .bo_destroy = drv_dumb_bo_destroy,
+ .bo_import = drv_prime_bo_import,
+ .bo_map = drv_dumb_bo_map,
+ .resolve_format = vgem_resolve_format,
+};
diff --git a/chromium/third_party/minigbm/src/virtio_gpu.c b/chromium/third_party/minigbm/src/virtio_gpu.c
new file mode 100644
index 00000000000..fe580cd15b6
--- /dev/null
+++ b/chromium/third_party/minigbm/src/virtio_gpu.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2016 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "drv_priv.h"
+#include "helpers.h"
+#include "util.h"
+
+#define MESA_LLVMPIPE_TILE_ORDER 6
+#define MESA_LLVMPIPE_TILE_SIZE (1 << MESA_LLVMPIPE_TILE_ORDER)
+
+static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888,
+ DRM_FORMAT_XRGB8888 };
+
+static const uint32_t texture_source_formats[] = { DRM_FORMAT_R8, DRM_FORMAT_YVU420,
+ DRM_FORMAT_YVU420_ANDROID };
+
+static int virtio_gpu_init(struct driver *drv)
+{
+ int ret;
+ ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
+ &LINEAR_METADATA, BO_USE_RENDER_MASK);
+ if (ret)
+ return ret;
+
+ ret = drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats),
+ &LINEAR_METADATA, BO_USE_TEXTURE_MASK);
+ if (ret)
+ return ret;
+
+ return drv_modify_linear_combinations(drv);
+}
+
+static int virtio_gpu_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+ uint32_t 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, flags);
+}
+
+static uint32_t virtio_gpu_resolve_format(uint32_t format, uint64_t usage)
+{
+ 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;
+ }
+}
+
+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,
+ .resolve_format = virtio_gpu_resolve_format,
+};