├── .clang-format ├── .travis.yml ├── Android.gralloc.mk ├── Android.mk ├── LICENSE ├── Makefile ├── PRESUBMIT.cfg ├── README.md ├── amdgpu.c ├── cirrus.c ├── common.mk ├── cros_gralloc ├── Makefile ├── cros_gralloc_buffer.cc ├── cros_gralloc_buffer.h ├── cros_gralloc_driver.cc ├── cros_gralloc_driver.h ├── cros_gralloc_handle.h ├── cros_gralloc_helpers.cc ├── cros_gralloc_helpers.h ├── cros_gralloc_spinlock.h ├── cros_gralloc_types.h ├── gralloc0 │ ├── gralloc0.cc │ └── tests │ │ ├── Makefile │ │ └── gralloctest.c ├── gralloc1 │ ├── cros_gralloc1_module.cc │ └── cros_gralloc1_module.h ├── i915_private_android.cc ├── i915_private_android.h └── i915_private_android_types.h ├── drv.c ├── drv.h ├── drv_priv.h ├── evdi.c ├── exynos.c ├── gbm.c ├── gbm.h ├── gbm.pc ├── gbm_helpers.c ├── gbm_helpers.h ├── gbm_priv.h ├── gma500.c ├── helpers.c ├── helpers.h ├── i915.c ├── i915_private.c ├── i915_private.h ├── i915_private_types.h ├── marvell.c ├── mediatek.c ├── nouveau.c ├── presubmit.sh ├── radeon.c ├── rockchip.c ├── tegra.c ├── travisci └── resources │ └── minigbm-install.tar.bz2 ├── udl.c ├── util.h ├── vc4.c ├── vgem.c └── virtio_gpu.c /.clang-format: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Chromium OS Authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style license that can be 3 | # found in the LICENSE file. 4 | 5 | BasedOnStyle: LLVM 6 | AllowShortFunctionsOnASingleLine: None 7 | AllowShortIfStatementsOnASingleLine: false 8 | AllowShortLoopsOnASingleLine: false 9 | BreakBeforeBraces: Linux 10 | ColumnLimit: 100 11 | IndentWidth: 8 12 | TabWidth: 8 13 | UseTab: Always 14 | Cpp11BracedListStyle: false 15 | IndentCaseLabels: false 16 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c++ 2 | sudo: required 3 | dist: trusty 4 | install: 5 | - sudo apt-get update 6 | - sudo apt-get install automake 7 | - sudo apt-get install autoconf 8 | - sudo apt-get install libtool 9 | - sudo apt-get install xutils-dev 10 | - sudo apt-get install libpciaccess-dev 11 | - sudo apt-get install python-mako 12 | - sudo dpkg -s python-mako 13 | - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y 14 | - sudo apt-get update 15 | - sudo apt-get install gcc-4.9 16 | - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 50 17 | - sudo apt-get install g++-4.9 18 | - sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.9 50 19 | script: 20 | - export HWC_BUILD_DIR=/tmp/ 21 | - export WLD=/tmp/hwc-install 22 | - export LD_LIBRARY_PATH=$WLD/lib 23 | - export PKG_CONFIG_PATH=$WLD/lib/pkgconfig/:$WLD/share/pkgconfig 24 | - export PATH=$WLD/bin:$PATH 25 | - export ACLOCAL_PATH=$WLD/share/aclocal 26 | - export ACLOCAL="aclocal -I $ACLOCAL_PATH" 27 | - export DRV_I915=1 28 | - tar -xvf travisci/resources/minigbm-install.tar.bz2 -C $HWC_BUILD_DIR 29 | - mkdir -p $WLD/share/aclocal 30 | - git clone https://github.com/intel/external-libdrm.git /tmp/libdrm 31 | - pushd /tmp/libdrm 32 | - ./autogen.sh --disable-radeon --disable-nouveau --disable-amdgpu --enable-udev --enable-libkms --prefix=$WLD 33 | - make -j5 && make install 34 | - popd 35 | - export DRV_I915=1 36 | - make CFLAGS=-DDRV_I915=1 -j5 37 | branches: 38 | only: 39 | - master 40 | -------------------------------------------------------------------------------- /Android.gralloc.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Chromium OS Authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style license that can be 3 | # found in the LICENSE file. 4 | 5 | LOCAL_CPP_EXTENSION := .cc 6 | 7 | LOCAL_SRC_FILES += \ 8 | cros_gralloc/cros_gralloc_buffer.cc \ 9 | cros_gralloc/cros_gralloc_driver.cc \ 10 | cros_gralloc/cros_gralloc_helpers.cc \ 11 | cros_gralloc/i915_private_android.cc 12 | 13 | ifeq ($(strip $(BOARD_USES_GRALLOC1)), true) 14 | LOCAL_SRC_FILES += cros_gralloc/gralloc1/cros_gralloc1_module.cc 15 | LOCAL_CPPFLAGS += -DUSE_GRALLOC1 16 | else 17 | LOCAL_SRC_FILES += cros_gralloc/gralloc0/gralloc0.cc 18 | endif 19 | -------------------------------------------------------------------------------- /Android.mk: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Chromium OS Authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style license that can be 3 | # found in the LICENSE file. 4 | 5 | ifeq ($(strip $(BOARD_USES_MINIGBM)), true) 6 | 7 | MINIGBM_GRALLOC_MK := $(call my-dir)/Android.gralloc.mk 8 | LOCAL_PATH := $(call my-dir) 9 | intel_drivers := i915 i965 iris 10 | include $(CLEAR_VARS) 11 | 12 | SUBDIRS := cros_gralloc 13 | 14 | LOCAL_SHARED_LIBRARIES := \ 15 | libcutils \ 16 | liblog \ 17 | libdrm \ 18 | libsync 19 | 20 | LOCAL_SRC_FILES := \ 21 | amdgpu.c \ 22 | cirrus.c \ 23 | drv.c \ 24 | evdi.c \ 25 | exynos.c \ 26 | gma500.c \ 27 | helpers.c \ 28 | i915.c \ 29 | i915_private.c \ 30 | marvell.c \ 31 | mediatek.c \ 32 | nouveau.c \ 33 | rockchip.c \ 34 | tegra.c \ 35 | udl.c \ 36 | vc4.c \ 37 | vgem.c \ 38 | virtio_gpu.c 39 | 40 | include $(MINIGBM_GRALLOC_MK) 41 | 42 | LOCAL_CPPFLAGS += -std=c++14 -D_GNU_SOURCE=1 -D_FILE_OFFSET_BITS=64 \ 43 | -Wno-switch -Wno-format -Wno-unused-variable 44 | LOCAL_CFLAGS += -Wall -Wsign-compare -Wpointer-arith \ 45 | -Wcast-qual -Wcast-align \ 46 | -D_GNU_SOURCE=1 -D_FILE_OFFSET_BITS=64 \ 47 | -Wno-unused-value -Wno-unused-parameter 48 | 49 | LOCAL_C_INCLUDES += frameworks/native/libs/nativebase/include \ 50 | frameworks/native/libs/nativewindow/include \ 51 | frameworks/native/libs/arect/include \ 52 | 53 | ifneq ($(filter $(intel_drivers), $(BOARD_GPU_DRIVERS)),) 54 | LOCAL_CPPFLAGS += -DDRV_I915 55 | LOCAL_CFLAGS += -DDRV_I915 56 | LOCAL_SHARED_LIBRARIES += libdrm_intel 57 | endif 58 | 59 | ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 27; echo $$?), 0) 60 | LOCAL_SHARED_LIBRARIES += libnativewindow 61 | LOCAL_STATIC_LIBRARIES += libarect 62 | LOCAL_HEADER_LIBRARIES += libnativebase_headers libsystem_headers libhardware_headers libutils_headers 63 | LOCAL_CFLAGS += -DUSE_VNDK 64 | endif 65 | 66 | LOCAL_CFLAGS += -Wno-error 67 | LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM) 68 | LOCAL_MODULE_TAGS := optional 69 | # The preferred path for vendor HALs is /vendor/lib/hw 70 | LOCAL_PROPRIETARY_MODULE := true 71 | LOCAL_MODULE_RELATIVE_PATH := hw 72 | LOCAL_MODULE_CLASS := SHARED_LIBRARIES 73 | LOCAL_MODULE_SUFFIX := $(TARGET_SHLIB_SUFFIX) 74 | include $(BUILD_SHARED_LIBRARY) 75 | 76 | endif 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 The Chromium OS Authors. All rights reserved. 2 | // 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are 5 | // met: 6 | // 7 | // * Redistributions of source code must retain the above copyright 8 | // notice, this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above 10 | // copyright notice, this list of conditions and the following disclaimer 11 | // in the documentation and/or other materials provided with the 12 | // distribution. 13 | // * Neither the name of Google Inc. nor the names of its 14 | // contributors may be used to endorse or promote products derived from 15 | // this software without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2014 The Chromium OS Authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style license that can be 3 | # found in the LICENSE file. 4 | 5 | include common.mk 6 | 7 | PC_DEPS = libdrm 8 | PC_CFLAGS := $(shell $(PKG_CONFIG) --cflags $(PC_DEPS)) 9 | PC_LIBS := $(shell $(PKG_CONFIG) --libs $(PC_DEPS)) 10 | 11 | CPPFLAGS += -D_GNU_SOURCE=1 12 | CFLAGS += -std=c99 -Wall -Wsign-compare -Wpointer-arith -Wcast-qual \ 13 | -Wcast-align -D_GNU_SOURCE=1 -D_FILE_OFFSET_BITS=64 14 | 15 | ifdef DRV_AMDGPU 16 | CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_amdgpu) 17 | LDLIBS += -lamdgpuaddr 18 | endif 19 | ifdef DRV_EXYNOS 20 | CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_exynos) 21 | endif 22 | ifdef DRV_I915 23 | CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_intel) 24 | endif 25 | ifdef DRV_RADEON 26 | CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_radeon) 27 | endif 28 | ifdef DRV_ROCKCHIP 29 | CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_rockchip) 30 | endif 31 | 32 | CPPFLAGS += $(PC_CFLAGS) 33 | LDLIBS += $(PC_LIBS) 34 | 35 | LIBDIR ?= /usr/lib/ 36 | 37 | GBM_VERSION_MAJOR := 1 38 | MINIGBM_VERSION := $(GBM_VERSION_MAJOR).0.0 39 | MINIGBM_FILENAME := libminigbm.so.$(MINIGBM_VERSION) 40 | 41 | CC_LIBRARY($(MINIGBM_FILENAME)): LDFLAGS += -Wl,-soname,libgbm.so.$(GBM_VERSION_MAJOR) 42 | CC_LIBRARY($(MINIGBM_FILENAME)): $(C_OBJECTS) 43 | 44 | all: CC_LIBRARY($(MINIGBM_FILENAME)) 45 | 46 | clean: CLEAN($(MINIGBM_FILENAME)) 47 | 48 | install: all 49 | mkdir -p $(DESTDIR)/$(LIBDIR) 50 | install -D -m 755 $(OUT)/$(MINIGBM_FILENAME) $(DESTDIR)/$(LIBDIR) 51 | ln -sf $(MINIGBM_FILENAME) $(DESTDIR)/$(LIBDIR)/libgbm.so 52 | ln -sf $(MINIGBM_FILENAME) $(DESTDIR)/$(LIBDIR)/libgbm.so.$(GBM_VERSION_MAJOR) 53 | install -D -m 0644 $(SRC)/gbm.pc $(DESTDIR)/$(LIBDIR)/pkgconfig/gbm.pc 54 | install -D -m 0644 $(SRC)/gbm.h $(DESTDIR)/include/gbm.h 55 | -------------------------------------------------------------------------------- /PRESUBMIT.cfg: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Chromium OS Authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style license that can be 3 | # found in the LICENSE file. 4 | [Hook Overrides] 5 | stray_whitespace_check: false 6 | long_line_check: false 7 | cros_license_check: false 8 | tab_check: false 9 | bug_field_check: false 10 | test_field_check: false 11 | [Hook Scripts] 12 | hook0 = ./presubmit.sh 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DISCONTINUATION OF PROJECT 2 | 3 | This project will no longer be maintained by Intel. 4 | 5 | Intel has ceased development and contributions including, but not limited to, maintenance, bug fixes, new releases, or updates, to this project. 6 | 7 | Intel no longer accepts patches to this project. 8 | 9 | If you have an ongoing need to use this project, are interested in independently developing it, or would like to maintain patches for the open source software community, please create your own fork of this project. 10 | 11 | Contact: webadmin@linux.intel.com 12 | -------------------------------------------------------------------------------- /amdgpu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | #ifdef DRV_AMDGPU 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "addrinterface.h" 17 | #include "drv_priv.h" 18 | #include "helpers.h" 19 | #include "util.h" 20 | 21 | #ifndef CIASICIDGFXENGINE_SOUTHERNISLAND 22 | #define CIASICIDGFXENGINE_SOUTHERNISLAND 0x0000000A 23 | #endif 24 | 25 | // clang-format off 26 | #define mmCC_RB_BACKEND_DISABLE 0x263d 27 | #define mmGB_TILE_MODE0 0x2644 28 | #define mmGB_MACROTILE_MODE0 0x2664 29 | #define mmGB_ADDR_CONFIG 0x263e 30 | #define mmMC_ARB_RAMCFG 0x9d8 31 | 32 | enum { 33 | FAMILY_UNKNOWN, 34 | FAMILY_SI, 35 | FAMILY_CI, 36 | FAMILY_KV, 37 | FAMILY_VI, 38 | FAMILY_CZ, 39 | FAMILY_PI, 40 | FAMILY_LAST, 41 | }; 42 | // clang-format on 43 | 44 | const static uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_RGB565, 45 | DRM_FORMAT_XBGR8888, DRM_FORMAT_XRGB8888 }; 46 | 47 | const static uint32_t texture_source_formats[] = { DRM_FORMAT_GR88, DRM_FORMAT_R8, DRM_FORMAT_NV21, 48 | DRM_FORMAT_NV12 }; 49 | 50 | static int amdgpu_set_metadata(int fd, uint32_t handle, struct amdgpu_bo_metadata *info) 51 | { 52 | struct drm_amdgpu_gem_metadata args = { 0 }; 53 | 54 | if (!info) 55 | return -EINVAL; 56 | 57 | args.handle = handle; 58 | args.op = AMDGPU_GEM_METADATA_OP_SET_METADATA; 59 | args.data.flags = info->flags; 60 | args.data.tiling_info = info->tiling_info; 61 | 62 | if (info->size_metadata > sizeof(args.data.data)) 63 | return -EINVAL; 64 | 65 | if (info->size_metadata) { 66 | args.data.data_size_bytes = info->size_metadata; 67 | memcpy(args.data.data, info->umd_metadata, info->size_metadata); 68 | } 69 | 70 | return drmCommandWriteRead(fd, DRM_AMDGPU_GEM_METADATA, &args, sizeof(args)); 71 | } 72 | 73 | static int amdgpu_read_mm_regs(int fd, unsigned dword_offset, unsigned count, uint32_t instance, 74 | uint32_t flags, uint32_t *values) 75 | { 76 | struct drm_amdgpu_info request; 77 | 78 | memset(&request, 0, sizeof(request)); 79 | request.return_pointer = (uintptr_t)values; 80 | request.return_size = count * sizeof(uint32_t); 81 | request.query = AMDGPU_INFO_READ_MMR_REG; 82 | request.read_mmr_reg.dword_offset = dword_offset; 83 | request.read_mmr_reg.count = count; 84 | request.read_mmr_reg.instance = instance; 85 | request.read_mmr_reg.flags = flags; 86 | 87 | return drmCommandWrite(fd, DRM_AMDGPU_INFO, &request, sizeof(struct drm_amdgpu_info)); 88 | } 89 | 90 | static int amdgpu_query_gpu(int fd, struct amdgpu_gpu_info *gpu_info) 91 | { 92 | int ret; 93 | uint32_t instance; 94 | 95 | if (!gpu_info) 96 | return -EINVAL; 97 | 98 | instance = AMDGPU_INFO_MMR_SH_INDEX_MASK << AMDGPU_INFO_MMR_SH_INDEX_SHIFT; 99 | 100 | ret = amdgpu_read_mm_regs(fd, mmCC_RB_BACKEND_DISABLE, 1, instance, 0, 101 | &gpu_info->backend_disable[0]); 102 | if (ret) 103 | return ret; 104 | /* extract bitfield CC_RB_BACKEND_DISABLE.BACKEND_DISABLE */ 105 | gpu_info->backend_disable[0] = (gpu_info->backend_disable[0] >> 16) & 0xff; 106 | 107 | ret = amdgpu_read_mm_regs(fd, mmGB_TILE_MODE0, 32, 0xffffffff, 0, gpu_info->gb_tile_mode); 108 | if (ret) 109 | return ret; 110 | 111 | ret = amdgpu_read_mm_regs(fd, mmGB_MACROTILE_MODE0, 16, 0xffffffff, 0, 112 | gpu_info->gb_macro_tile_mode); 113 | if (ret) 114 | return ret; 115 | 116 | ret = amdgpu_read_mm_regs(fd, mmGB_ADDR_CONFIG, 1, 0xffffffff, 0, &gpu_info->gb_addr_cfg); 117 | if (ret) 118 | return ret; 119 | 120 | ret = amdgpu_read_mm_regs(fd, mmMC_ARB_RAMCFG, 1, 0xffffffff, 0, &gpu_info->mc_arb_ramcfg); 121 | if (ret) 122 | return ret; 123 | 124 | return 0; 125 | } 126 | 127 | static void *ADDR_API alloc_sys_mem(const ADDR_ALLOCSYSMEM_INPUT *in) 128 | { 129 | return malloc(in->sizeInBytes); 130 | } 131 | 132 | static ADDR_E_RETURNCODE ADDR_API free_sys_mem(const ADDR_FREESYSMEM_INPUT *in) 133 | { 134 | free(in->pVirtAddr); 135 | return ADDR_OK; 136 | } 137 | 138 | static int amdgpu_addrlib_compute(void *addrlib, uint32_t width, uint32_t height, uint32_t format, 139 | uint64_t use_flags, uint32_t *tiling_flags, 140 | ADDR_COMPUTE_SURFACE_INFO_OUTPUT *addr_out) 141 | { 142 | ADDR_COMPUTE_SURFACE_INFO_INPUT addr_surf_info_in = { 0 }; 143 | ADDR_TILEINFO addr_tile_info = { 0 }; 144 | ADDR_TILEINFO addr_tile_info_out = { 0 }; 145 | uint32_t bits_per_pixel; 146 | 147 | addr_surf_info_in.size = sizeof(ADDR_COMPUTE_SURFACE_INFO_INPUT); 148 | 149 | /* Set the requested tiling mode. */ 150 | addr_surf_info_in.tileMode = ADDR_TM_2D_TILED_THIN1; 151 | if (use_flags & 152 | (BO_USE_CURSOR | BO_USE_LINEAR | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN)) 153 | addr_surf_info_in.tileMode = ADDR_TM_LINEAR_ALIGNED; 154 | else if (width <= 16 || height <= 16) 155 | addr_surf_info_in.tileMode = ADDR_TM_1D_TILED_THIN1; 156 | 157 | bits_per_pixel = drv_stride_from_format(format, 1, 0) * 8; 158 | /* Bits per pixel should be calculated from format*/ 159 | addr_surf_info_in.bpp = bits_per_pixel; 160 | addr_surf_info_in.numSamples = 1; 161 | addr_surf_info_in.width = width; 162 | addr_surf_info_in.height = height; 163 | addr_surf_info_in.numSlices = 1; 164 | addr_surf_info_in.pTileInfo = &addr_tile_info; 165 | addr_surf_info_in.tileIndex = -1; 166 | 167 | /* This disables incorrect calculations (hacks) in addrlib. */ 168 | addr_surf_info_in.flags.noStencil = 1; 169 | 170 | /* Set the micro tile type. */ 171 | if (use_flags & BO_USE_SCANOUT) 172 | addr_surf_info_in.tileType = ADDR_DISPLAYABLE; 173 | else 174 | addr_surf_info_in.tileType = ADDR_NON_DISPLAYABLE; 175 | 176 | addr_out->size = sizeof(ADDR_COMPUTE_SURFACE_INFO_OUTPUT); 177 | addr_out->pTileInfo = &addr_tile_info_out; 178 | 179 | if (AddrComputeSurfaceInfo(addrlib, &addr_surf_info_in, addr_out) != ADDR_OK) 180 | return -EINVAL; 181 | 182 | ADDR_CONVERT_TILEINFOTOHW_INPUT s_in = { 0 }; 183 | ADDR_CONVERT_TILEINFOTOHW_OUTPUT s_out = { 0 }; 184 | ADDR_TILEINFO s_tile_hw_info_out = { 0 }; 185 | 186 | s_in.size = sizeof(ADDR_CONVERT_TILEINFOTOHW_INPUT); 187 | /* Convert from real value to HW value */ 188 | s_in.reverse = 0; 189 | s_in.pTileInfo = &addr_tile_info_out; 190 | s_in.tileIndex = -1; 191 | 192 | s_out.size = sizeof(ADDR_CONVERT_TILEINFOTOHW_OUTPUT); 193 | s_out.pTileInfo = &s_tile_hw_info_out; 194 | 195 | if (AddrConvertTileInfoToHW(addrlib, &s_in, &s_out) != ADDR_OK) 196 | return -EINVAL; 197 | 198 | if (addr_out->tileMode >= ADDR_TM_2D_TILED_THIN1) 199 | /* 2D_TILED_THIN1 */ 200 | *tiling_flags |= AMDGPU_TILING_SET(ARRAY_MODE, 4); 201 | else if (addr_out->tileMode >= ADDR_TM_1D_TILED_THIN1) 202 | /* 1D_TILED_THIN1 */ 203 | *tiling_flags |= AMDGPU_TILING_SET(ARRAY_MODE, 2); 204 | else 205 | /* LINEAR_ALIGNED */ 206 | *tiling_flags |= AMDGPU_TILING_SET(ARRAY_MODE, 1); 207 | 208 | *tiling_flags |= AMDGPU_TILING_SET(BANK_WIDTH, drv_log_base2(addr_tile_info_out.bankWidth)); 209 | *tiling_flags |= 210 | AMDGPU_TILING_SET(BANK_HEIGHT, drv_log_base2(addr_tile_info_out.bankHeight)); 211 | *tiling_flags |= AMDGPU_TILING_SET(TILE_SPLIT, s_tile_hw_info_out.tileSplitBytes); 212 | *tiling_flags |= AMDGPU_TILING_SET(MACRO_TILE_ASPECT, 213 | drv_log_base2(addr_tile_info_out.macroAspectRatio)); 214 | *tiling_flags |= AMDGPU_TILING_SET(PIPE_CONFIG, s_tile_hw_info_out.pipeConfig); 215 | *tiling_flags |= AMDGPU_TILING_SET(NUM_BANKS, s_tile_hw_info_out.banks); 216 | 217 | return 0; 218 | } 219 | 220 | static void *amdgpu_addrlib_init(int fd) 221 | { 222 | int ret; 223 | ADDR_CREATE_INPUT addr_create_input = { 0 }; 224 | ADDR_CREATE_OUTPUT addr_create_output = { 0 }; 225 | ADDR_REGISTER_VALUE reg_value = { 0 }; 226 | ADDR_CREATE_FLAGS create_flags = { { 0 } }; 227 | ADDR_E_RETURNCODE addr_ret; 228 | 229 | addr_create_input.size = sizeof(ADDR_CREATE_INPUT); 230 | addr_create_output.size = sizeof(ADDR_CREATE_OUTPUT); 231 | 232 | struct amdgpu_gpu_info gpu_info = { 0 }; 233 | 234 | ret = amdgpu_query_gpu(fd, &gpu_info); 235 | 236 | if (ret) { 237 | fprintf(stderr, "[%s]failed with error =%d\n", __func__, ret); 238 | return NULL; 239 | } 240 | 241 | reg_value.noOfBanks = gpu_info.mc_arb_ramcfg & 0x3; 242 | reg_value.gbAddrConfig = gpu_info.gb_addr_cfg; 243 | reg_value.noOfRanks = (gpu_info.mc_arb_ramcfg & 0x4) >> 2; 244 | 245 | reg_value.backendDisables = gpu_info.backend_disable[0]; 246 | reg_value.pTileConfig = gpu_info.gb_tile_mode; 247 | reg_value.noOfEntries = sizeof(gpu_info.gb_tile_mode) / sizeof(gpu_info.gb_tile_mode[0]); 248 | reg_value.pMacroTileConfig = gpu_info.gb_macro_tile_mode; 249 | reg_value.noOfMacroEntries = 250 | sizeof(gpu_info.gb_macro_tile_mode) / sizeof(gpu_info.gb_macro_tile_mode[0]); 251 | create_flags.value = 0; 252 | create_flags.useTileIndex = 1; 253 | 254 | addr_create_input.chipEngine = CIASICIDGFXENGINE_SOUTHERNISLAND; 255 | 256 | addr_create_input.chipFamily = FAMILY_CZ; 257 | addr_create_input.createFlags = create_flags; 258 | addr_create_input.callbacks.allocSysMem = alloc_sys_mem; 259 | addr_create_input.callbacks.freeSysMem = free_sys_mem; 260 | addr_create_input.callbacks.debugPrint = 0; 261 | addr_create_input.regValue = reg_value; 262 | 263 | addr_ret = AddrCreate(&addr_create_input, &addr_create_output); 264 | 265 | if (addr_ret != ADDR_OK) { 266 | fprintf(stderr, "[%s]failed error =%d\n", __func__, addr_ret); 267 | return NULL; 268 | } 269 | 270 | return addr_create_output.hLib; 271 | } 272 | 273 | static int amdgpu_init(struct driver *drv) 274 | { 275 | int ret; 276 | void *addrlib; 277 | struct format_metadata metadata; 278 | uint64_t use_flags = BO_USE_RENDER_MASK; 279 | 280 | addrlib = amdgpu_addrlib_init(drv_get_fd(drv)); 281 | if (!addrlib) 282 | return -1; 283 | 284 | drv->priv = addrlib; 285 | 286 | ret = drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats), 287 | &LINEAR_METADATA, BO_USE_TEXTURE_MASK); 288 | if (ret) 289 | return ret; 290 | 291 | drv_modify_combination(drv, DRM_FORMAT_NV21, &LINEAR_METADATA, BO_USE_SCANOUT); 292 | drv_modify_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA, BO_USE_SCANOUT); 293 | 294 | metadata.tiling = ADDR_DISPLAYABLE << 16 | ADDR_TM_LINEAR_ALIGNED; 295 | metadata.priority = 2; 296 | metadata.modifier = DRM_FORMAT_MOD_LINEAR; 297 | 298 | ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), 299 | &metadata, use_flags); 300 | if (ret) 301 | return ret; 302 | 303 | drv_modify_combination(drv, DRM_FORMAT_ARGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT); 304 | drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT); 305 | drv_modify_combination(drv, DRM_FORMAT_XBGR8888, &metadata, BO_USE_SCANOUT); 306 | 307 | metadata.tiling = ADDR_NON_DISPLAYABLE << 16 | ADDR_TM_LINEAR_ALIGNED; 308 | metadata.priority = 3; 309 | metadata.modifier = DRM_FORMAT_MOD_LINEAR; 310 | 311 | ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), 312 | &metadata, use_flags); 313 | if (ret) 314 | return ret; 315 | 316 | use_flags &= ~BO_USE_SW_WRITE_OFTEN; 317 | use_flags &= ~BO_USE_SW_READ_OFTEN; 318 | use_flags &= ~BO_USE_LINEAR; 319 | 320 | metadata.tiling = ADDR_DISPLAYABLE << 16 | ADDR_TM_2D_TILED_THIN1; 321 | metadata.priority = 4; 322 | 323 | ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), 324 | &metadata, use_flags); 325 | if (ret) 326 | return ret; 327 | 328 | drv_modify_combination(drv, DRM_FORMAT_ARGB8888, &metadata, BO_USE_SCANOUT); 329 | drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_SCANOUT); 330 | drv_modify_combination(drv, DRM_FORMAT_XBGR8888, &metadata, BO_USE_SCANOUT); 331 | 332 | metadata.tiling = ADDR_NON_DISPLAYABLE << 16 | ADDR_TM_2D_TILED_THIN1; 333 | metadata.priority = 5; 334 | 335 | ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), 336 | &metadata, use_flags); 337 | if (ret) 338 | return ret; 339 | 340 | return ret; 341 | } 342 | 343 | static void amdgpu_close(struct driver *drv) 344 | { 345 | AddrDestroy(drv->priv); 346 | drv->priv = NULL; 347 | } 348 | 349 | static int amdgpu_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, 350 | uint64_t use_flags) 351 | { 352 | void *addrlib = bo->drv->priv; 353 | union drm_amdgpu_gem_create gem_create; 354 | struct amdgpu_bo_metadata metadata = { 0 }; 355 | ADDR_COMPUTE_SURFACE_INFO_OUTPUT addr_out = { 0 }; 356 | uint32_t tiling_flags = 0; 357 | size_t plane; 358 | int ret; 359 | 360 | if (format == DRM_FORMAT_NV12 || format == DRM_FORMAT_NV21) { 361 | drv_bo_from_format(bo, ALIGN(width, 64), height, format); 362 | } else { 363 | if (amdgpu_addrlib_compute(addrlib, width, height, format, use_flags, &tiling_flags, 364 | &addr_out) < 0) 365 | return -EINVAL; 366 | 367 | bo->tiling = tiling_flags; 368 | /* RGB has 1 plane only */ 369 | bo->offsets[0] = 0; 370 | bo->total_size = bo->sizes[0] = addr_out.surfSize; 371 | bo->strides[0] = addr_out.pixelPitch * DIV_ROUND_UP(addr_out.pixelBits, 8); 372 | } 373 | 374 | memset(&gem_create, 0, sizeof(gem_create)); 375 | 376 | gem_create.in.bo_size = bo->total_size; 377 | gem_create.in.alignment = addr_out.baseAlign; 378 | /* Set the placement. */ 379 | gem_create.in.domains = AMDGPU_GEM_DOMAIN_VRAM; 380 | gem_create.in.domain_flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; 381 | /* Allocate the buffer with the preferred heap. */ 382 | ret = drmCommandWriteRead(drv_get_fd(bo->drv), DRM_AMDGPU_GEM_CREATE, &gem_create, 383 | sizeof(gem_create)); 384 | 385 | if (ret < 0) 386 | return ret; 387 | 388 | metadata.tiling_info = tiling_flags; 389 | 390 | for (plane = 0; plane < bo->num_planes; plane++) 391 | bo->handles[plane].u32 = gem_create.out.handle; 392 | 393 | ret = amdgpu_set_metadata(drv_get_fd(bo->drv), bo->handles[0].u32, &metadata); 394 | 395 | return ret; 396 | } 397 | 398 | static void *amdgpu_bo_map(struct bo *bo, struct map_info *data, size_t plane, uint32_t map_flags) 399 | { 400 | int ret; 401 | union drm_amdgpu_gem_mmap gem_map; 402 | 403 | memset(&gem_map, 0, sizeof(gem_map)); 404 | gem_map.in.handle = bo->handles[plane].u32; 405 | 406 | ret = drmIoctl(bo->drv->fd, DRM_IOCTL_AMDGPU_GEM_MMAP, &gem_map); 407 | if (ret) { 408 | fprintf(stderr, "drv: DRM_IOCTL_AMDGPU_GEM_MMAP failed\n"); 409 | return MAP_FAILED; 410 | } 411 | 412 | data->length = bo->total_size; 413 | 414 | return mmap(0, bo->total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd, 415 | gem_map.out.addr_ptr); 416 | } 417 | 418 | static uint32_t amdgpu_resolve_format(uint32_t format, uint64_t use_flags) 419 | { 420 | switch (format) { 421 | case DRM_FORMAT_FLEX_YCbCr_420_888: 422 | return DRM_FORMAT_NV12; 423 | default: 424 | return format; 425 | } 426 | } 427 | 428 | struct backend backend_amdgpu = { 429 | .name = "amdgpu", 430 | .init = amdgpu_init, 431 | .close = amdgpu_close, 432 | .bo_create = amdgpu_bo_create, 433 | .bo_destroy = drv_gem_bo_destroy, 434 | .bo_import = drv_prime_bo_import, 435 | .bo_map = amdgpu_bo_map, 436 | .bo_unmap = drv_bo_munmap, 437 | .resolve_format = amdgpu_resolve_format, 438 | }; 439 | 440 | #endif 441 | -------------------------------------------------------------------------------- /cirrus.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #include "drv_priv.h" 8 | #include "helpers.h" 9 | #include "util.h" 10 | 11 | const static uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_RGB888, 12 | DRM_FORMAT_XRGB8888 }; 13 | 14 | static int cirrus_init(struct driver *drv) 15 | { 16 | int ret; 17 | ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), 18 | &LINEAR_METADATA, BO_USE_RENDER_MASK); 19 | if (ret) 20 | return ret; 21 | 22 | return drv_modify_linear_combinations(drv); 23 | } 24 | 25 | struct backend backend_cirrus = { 26 | .name = "cirrus", 27 | .init = cirrus_init, 28 | .bo_create = drv_dumb_bo_create, 29 | .bo_destroy = drv_dumb_bo_destroy, 30 | .bo_import = drv_prime_bo_import, 31 | .bo_map = drv_dumb_bo_map, 32 | .bo_unmap = drv_bo_munmap, 33 | }; 34 | -------------------------------------------------------------------------------- /cros_gralloc/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2016 The Chromium OS Authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style license that can be 3 | # found in the LICENSE file. 4 | 5 | GRALLOC = gralloc.cros.so 6 | 7 | SRCS = $(wildcard *.cc) 8 | SRCS += $(wildcard ../*.c) 9 | 10 | SRCS += $(wildcard gralloc0/*.cc) 11 | 12 | SOURCES = $(filter-out ../gbm%, $(SRCS)) 13 | PKG_CONFIG ?= pkg-config 14 | 15 | VPATH = $(dir $(SOURCES)) 16 | LIBDRM_CFLAGS := $(shell $(PKG_CONFIG) --cflags libdrm) 17 | LIBDRM_LIBS := $(shell $(PKG_CONFIG) --libs libdrm) 18 | 19 | CPPFLAGS += -Wall -fPIC -Werror -flto $(LIBDRM_CFLAGS) 20 | CXXFLAGS += -std=c++14 21 | CFLAGS += -std=c99 22 | LIBS += -shared -lcutils -lhardware -lsync $(LIBDRM_LIBS) 23 | 24 | ifdef DRV_AMDGPU 25 | LIBS += -lamdgpuaddr 26 | endif 27 | 28 | OBJS = $(foreach source, $(SOURCES), $(addsuffix .o, $(basename $(source)))) 29 | 30 | OBJECTS = $(addprefix $(TARGET_DIR), $(notdir $(OBJS))) 31 | LIBRARY = $(addprefix $(TARGET_DIR), $(GRALLOC)) 32 | 33 | .PHONY: all clean 34 | 35 | all: $(LIBRARY) 36 | 37 | $(LIBRARY): $(OBJECTS) 38 | 39 | clean: 40 | $(RM) $(LIBRARY) 41 | $(RM) $(OBJECTS) 42 | 43 | $(LIBRARY): 44 | $(CXX) $(CPPFLAGS) $(CXXFLAGS) $^ -o $@ $(LIBS) 45 | 46 | $(TARGET_DIR)%.o: %.cc 47 | $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $^ -o $@ -MMD 48 | 49 | $(TARGET_DIR)%.o: %.c 50 | $(CC) $(CPPFLAGS) $(CFLAGS) -c $^ -o $@ -MMD 51 | -------------------------------------------------------------------------------- /cros_gralloc/cros_gralloc_buffer.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #include "cros_gralloc_buffer.h" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | cros_gralloc_buffer::cros_gralloc_buffer(uint32_t id, struct bo *acquire_bo, 14 | struct cros_gralloc_handle *acquire_handle) 15 | : id_(id), bo_(acquire_bo), hnd_(acquire_handle), refcount_(1), lockcount_(0) 16 | { 17 | assert(bo_); 18 | num_planes_ = drv_bo_get_num_planes(bo_); 19 | for (uint32_t plane = 0; plane < num_planes_; plane++) 20 | lock_data_[plane] = nullptr; 21 | } 22 | 23 | cros_gralloc_buffer::~cros_gralloc_buffer() 24 | { 25 | drv_bo_destroy(bo_); 26 | if (hnd_) { 27 | native_handle_close(&hnd_->base); 28 | delete hnd_; 29 | } 30 | } 31 | 32 | uint32_t cros_gralloc_buffer::get_id() const 33 | { 34 | return id_; 35 | } 36 | 37 | int32_t cros_gralloc_buffer::increase_refcount() 38 | { 39 | return ++refcount_; 40 | } 41 | 42 | int32_t cros_gralloc_buffer::decrease_refcount() 43 | { 44 | assert(refcount_ > 0); 45 | return --refcount_; 46 | } 47 | 48 | int32_t cros_gralloc_buffer::lock(uint32_t map_flags, uint8_t *addr[DRV_MAX_PLANES]) 49 | { 50 | void *vaddr = nullptr; 51 | 52 | memset(addr, 0, DRV_MAX_PLANES * sizeof(*addr)); 53 | 54 | /* 55 | * Gralloc consumers don't support more than one kernel buffer per buffer object yet, so 56 | * just use the first kernel buffer. 57 | */ 58 | if (drv_num_buffers_per_bo(bo_) != 1) { 59 | cros_gralloc_error("Can only support one buffer per bo."); 60 | return -EINVAL; 61 | } 62 | 63 | if (map_flags) { 64 | if (lock_data_[0]) { 65 | drv_bo_invalidate(bo_, lock_data_[0]); 66 | vaddr = lock_data_[0]->addr; 67 | } else { 68 | vaddr = drv_bo_map(bo_, 0, 0, drv_bo_get_width(bo_), drv_bo_get_height(bo_), 69 | map_flags, &lock_data_[0], 0); 70 | } 71 | 72 | if (vaddr == MAP_FAILED) { 73 | cros_gralloc_error("Mapping failed."); 74 | return -EFAULT; 75 | } 76 | } 77 | 78 | for (uint32_t plane = 0; plane < num_planes_; plane++) 79 | addr[plane] = static_cast(vaddr) + drv_bo_get_plane_offset(bo_, plane); 80 | 81 | lockcount_++; 82 | return 0; 83 | } 84 | 85 | int32_t cros_gralloc_buffer::unlock() 86 | { 87 | if (lockcount_ <= 0) { 88 | cros_gralloc_error("Buffer was not locked."); 89 | return -EINVAL; 90 | } 91 | 92 | if (!--lockcount_) { 93 | if (lock_data_[0]) { 94 | drv_bo_unmap(bo_, lock_data_[0]); 95 | lock_data_[0] = nullptr; 96 | } 97 | } 98 | 99 | return 0; 100 | } 101 | -------------------------------------------------------------------------------- /cros_gralloc/cros_gralloc_buffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifndef CROS_GRALLOC_BUFFER_H 8 | #define CROS_GRALLOC_BUFFER_H 9 | 10 | #include "../drv.h" 11 | #include "cros_gralloc_helpers.h" 12 | 13 | class cros_gralloc_buffer 14 | { 15 | public: 16 | cros_gralloc_buffer(uint32_t id, struct bo *acquire_bo, 17 | struct cros_gralloc_handle *acquire_handle); 18 | ~cros_gralloc_buffer(); 19 | 20 | uint32_t get_id() const; 21 | 22 | /* The new reference count is returned by both these functions. */ 23 | int32_t increase_refcount(); 24 | int32_t decrease_refcount(); 25 | 26 | int32_t lock(uint32_t map_flags, uint8_t *addr[DRV_MAX_PLANES]); 27 | int32_t unlock(); 28 | 29 | private: 30 | cros_gralloc_buffer(cros_gralloc_buffer const &); 31 | cros_gralloc_buffer operator=(cros_gralloc_buffer const &); 32 | 33 | uint32_t id_; 34 | struct bo *bo_; 35 | struct cros_gralloc_handle *hnd_; 36 | 37 | int32_t refcount_; 38 | int32_t lockcount_; 39 | uint32_t num_planes_; 40 | 41 | struct map_info *lock_data_[DRV_MAX_PLANES]; 42 | }; 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /cros_gralloc/cros_gralloc_driver.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #include "cros_gralloc_driver.h" 8 | #include "../util.h" 9 | 10 | #include "i915_private_android.h" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | cros_gralloc_driver::cros_gralloc_driver() : drv_(nullptr) 19 | { 20 | } 21 | 22 | cros_gralloc_driver::~cros_gralloc_driver() 23 | { 24 | buffers_.clear(); 25 | handles_.clear(); 26 | 27 | if (drv_) { 28 | drv_destroy(drv_); 29 | drv_ = nullptr; 30 | } 31 | } 32 | 33 | int32_t cros_gralloc_driver::init() 34 | { 35 | /* 36 | * Create a driver from rendernode while filtering out 37 | * the specified undesired driver. 38 | * 39 | * TODO(gsingh): Enable render nodes on udl/evdi. 40 | */ 41 | 42 | int fd; 43 | drmVersionPtr version; 44 | char const *str = "%s/renderD%d"; 45 | const char *undesired[2] = { "vgem", nullptr }; 46 | uint32_t num_nodes = 63; 47 | uint32_t min_node = 128; 48 | uint32_t max_node = (min_node + num_nodes); 49 | 50 | for (uint32_t i = 0; i < ARRAY_SIZE(undesired); i++) { 51 | for (uint32_t j = min_node; j < max_node; j++) { 52 | char *node; 53 | if (asprintf(&node, str, DRM_DIR_NAME, j) < 0) 54 | continue; 55 | 56 | fd = open(node, O_RDWR, 0); 57 | free(node); 58 | 59 | if (fd < 0) 60 | continue; 61 | 62 | version = drmGetVersion(fd); 63 | if (!version) { 64 | close(fd); 65 | continue; 66 | } 67 | 68 | if (undesired[i] && !strcmp(version->name, undesired[i])) { 69 | drmFreeVersion(version); 70 | close(fd); 71 | continue; 72 | } 73 | 74 | drmFreeVersion(version); 75 | drv_ = drv_create(fd); 76 | if (drv_) { 77 | return 0; 78 | } 79 | 80 | close(fd); 81 | } 82 | } 83 | 84 | return -ENODEV; 85 | } 86 | 87 | bool cros_gralloc_driver::is_supported(const struct cros_gralloc_buffer_descriptor *descriptor) 88 | { 89 | struct combination *combo; 90 | uint32_t resolved_format; 91 | resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags); 92 | combo = drv_get_combination(drv_, resolved_format, descriptor->use_flags); 93 | return (combo != nullptr); 94 | } 95 | 96 | int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descriptor *descriptor, 97 | buffer_handle_t *out_handle) 98 | { 99 | uint32_t id; 100 | uint64_t mod; 101 | size_t num_planes; 102 | uint32_t resolved_format; 103 | 104 | struct bo *bo; 105 | struct cros_gralloc_handle *hnd; 106 | 107 | resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags); 108 | if (descriptor->modifier == 0) { 109 | bo = drv_bo_create(drv_, descriptor->width, descriptor->height, resolved_format, 110 | descriptor->use_flags); 111 | } else { 112 | bo = drv_bo_create_with_modifiers(drv_, descriptor->width, descriptor->height, 113 | resolved_format, &descriptor->modifier, 1); 114 | } 115 | if (!bo) { 116 | cros_gralloc_error("Failed to create bo."); 117 | return -ENOMEM; 118 | } 119 | 120 | /* 121 | * If there is a desire for more than one kernel buffer, this can be 122 | * removed once the ArcCodec and Wayland service have the ability to 123 | * send more than one fd. GL/Vulkan drivers may also have to modified. 124 | */ 125 | if (drv_num_buffers_per_bo(bo) != 1) { 126 | drv_bo_destroy(bo); 127 | cros_gralloc_error("Can only support one buffer per bo."); 128 | return -EINVAL; 129 | } 130 | 131 | hnd = new cros_gralloc_handle(); 132 | num_planes = drv_bo_get_num_planes(bo); 133 | 134 | hnd->base.version = sizeof(hnd->base); 135 | hnd->base.numFds = num_planes; 136 | hnd->base.numInts = handle_data_size - num_planes; 137 | 138 | for (size_t plane = 0; plane < num_planes; plane++) { 139 | hnd->fds[plane] = drv_bo_get_plane_fd(bo, plane); 140 | hnd->strides[plane] = drv_bo_get_plane_stride(bo, plane); 141 | hnd->offsets[plane] = drv_bo_get_plane_offset(bo, plane); 142 | hnd->sizes[plane] = drv_bo_get_plane_size(bo, plane); 143 | 144 | mod = drv_bo_get_plane_format_modifier(bo, plane); 145 | hnd->format_modifiers[2 * plane] = static_cast(mod >> 32); 146 | hnd->format_modifiers[2 * plane + 1] = static_cast(mod); 147 | } 148 | 149 | hnd->width = drv_bo_get_width(bo); 150 | hnd->height = drv_bo_get_height(bo); 151 | hnd->format = drv_bo_get_format(bo); 152 | hnd->tiling_mode = drv_bo_get_stride_or_tiling(bo); 153 | hnd->use_flags[0] = static_cast(descriptor->use_flags >> 32); 154 | hnd->use_flags[1] = static_cast(descriptor->use_flags); 155 | hnd->pixel_stride = drv_bo_get_stride_in_pixels(bo); 156 | hnd->magic = cros_gralloc_magic; 157 | int32_t format = i915_private_invert_format(hnd->format); 158 | if (format == 0) { 159 | format = descriptor->droid_format; 160 | } 161 | hnd->droid_format = format; 162 | hnd->usage = descriptor->producer_usage; 163 | hnd->producer_usage = descriptor->producer_usage; 164 | hnd->consumer_usage = descriptor->consumer_usage; 165 | 166 | id = drv_bo_get_plane_handle(bo, 0).u32; 167 | auto buffer = new cros_gralloc_buffer(id, bo, hnd); 168 | 169 | SCOPED_SPIN_LOCK(mutex_); 170 | buffers_.emplace(id, buffer); 171 | handles_.emplace(hnd, std::make_pair(buffer, 1)); 172 | *out_handle = &hnd->base; 173 | return 0; 174 | } 175 | 176 | int32_t cros_gralloc_driver::retain(buffer_handle_t handle) 177 | { 178 | uint32_t id; 179 | SCOPED_SPIN_LOCK(mutex_); 180 | 181 | auto hnd = cros_gralloc_convert_handle(handle); 182 | if (!hnd) { 183 | cros_gralloc_error("Invalid handle."); 184 | return -EINVAL; 185 | } 186 | 187 | auto buffer = get_buffer(hnd); 188 | if (buffer) { 189 | handles_[hnd].second++; 190 | buffer->increase_refcount(); 191 | return 0; 192 | } 193 | 194 | if (drmPrimeFDToHandle(drv_get_fd(drv_), hnd->fds[0], &id)) { 195 | cros_gralloc_error("drmPrimeFDToHandle failed."); 196 | return -errno; 197 | } 198 | 199 | if (buffers_.count(id)) { 200 | buffer = buffers_[id]; 201 | buffer->increase_refcount(); 202 | } else { 203 | struct bo *bo; 204 | struct drv_import_fd_data data; 205 | data.format = hnd->format; 206 | data.width = hnd->width; 207 | data.height = hnd->height; 208 | data.use_flags = static_cast(hnd->use_flags[0]) << 32; 209 | data.use_flags |= hnd->use_flags[1]; 210 | 211 | memcpy(data.fds, hnd->fds, sizeof(data.fds)); 212 | memcpy(data.strides, hnd->strides, sizeof(data.strides)); 213 | memcpy(data.offsets, hnd->offsets, sizeof(data.offsets)); 214 | for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++) { 215 | data.format_modifiers[plane] = 216 | static_cast(hnd->format_modifiers[2 * plane]) << 32; 217 | data.format_modifiers[plane] |= hnd->format_modifiers[2 * plane + 1]; 218 | } 219 | 220 | bo = drv_bo_import(drv_, &data); 221 | if (!bo) 222 | return -EFAULT; 223 | 224 | id = drv_bo_get_plane_handle(bo, 0).u32; 225 | 226 | buffer = new cros_gralloc_buffer(id, bo, nullptr); 227 | buffers_.emplace(id, buffer); 228 | } 229 | 230 | handles_.emplace(hnd, std::make_pair(buffer, 1)); 231 | return 0; 232 | } 233 | 234 | int32_t cros_gralloc_driver::release(buffer_handle_t handle) 235 | { 236 | SCOPED_SPIN_LOCK(mutex_); 237 | 238 | auto hnd = cros_gralloc_convert_handle(handle); 239 | if (!hnd) { 240 | cros_gralloc_error("Invalid handle."); 241 | return -EINVAL; 242 | } 243 | 244 | auto buffer = get_buffer(hnd); 245 | if (!buffer) { 246 | uint32_t id = -1; 247 | if (drmPrimeFDToHandle(drv_get_fd(drv_), hnd->fds[0], &id)) { 248 | cros_gralloc_error("drmPrimeFDToHandle failed."); 249 | return -errno; 250 | } 251 | if (buffers_.count(id)) { 252 | buffer = buffers_[id]; 253 | buffer->increase_refcount(); 254 | } else { 255 | cros_gralloc_error("Could not found reference"); 256 | return -EINVAL; 257 | } 258 | } else if (!--handles_[hnd].second) 259 | handles_.erase(hnd); 260 | 261 | if (buffer->decrease_refcount() == 0) { 262 | buffers_.erase(buffer->get_id()); 263 | delete buffer; 264 | } 265 | 266 | return 0; 267 | } 268 | 269 | int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence, uint32_t map_flags, 270 | uint8_t *addr[DRV_MAX_PLANES]) 271 | { 272 | int32_t ret = cros_gralloc_sync_wait(acquire_fence); 273 | if (ret) 274 | return ret; 275 | 276 | SCOPED_SPIN_LOCK(mutex_); 277 | auto hnd = cros_gralloc_convert_handle(handle); 278 | if (!hnd) { 279 | cros_gralloc_error("Invalid handle."); 280 | return -EINVAL; 281 | } 282 | 283 | auto buffer = get_buffer(hnd); 284 | if (!buffer) { 285 | cros_gralloc_error("Invalid Reference."); 286 | return -EINVAL; 287 | } 288 | 289 | return buffer->lock(map_flags, addr); 290 | } 291 | 292 | int32_t cros_gralloc_driver::unlock(buffer_handle_t handle, int32_t *release_fence) 293 | { 294 | SCOPED_SPIN_LOCK(mutex_); 295 | 296 | auto hnd = cros_gralloc_convert_handle(handle); 297 | if (!hnd) { 298 | cros_gralloc_error("Invalid handle."); 299 | return -EINVAL; 300 | } 301 | 302 | auto buffer = get_buffer(hnd); 303 | if (!buffer) { 304 | cros_gralloc_error("Invalid Reference."); 305 | return -EINVAL; 306 | } 307 | 308 | /* 309 | * From the ANativeWindow::dequeueBuffer documentation: 310 | * 311 | * "A value of -1 indicates that the caller may access the buffer immediately without 312 | * waiting on a fence." 313 | */ 314 | *release_fence = -1; 315 | return buffer->unlock(); 316 | } 317 | 318 | int32_t cros_gralloc_driver::get_backing_store(buffer_handle_t handle, uint64_t *out_store) 319 | { 320 | SCOPED_SPIN_LOCK(mutex_); 321 | 322 | auto hnd = cros_gralloc_convert_handle(handle); 323 | if (!hnd) { 324 | cros_gralloc_error("Invalid handle."); 325 | return -EINVAL; 326 | } 327 | 328 | auto buffer = get_buffer(hnd); 329 | if (!buffer) { 330 | cros_gralloc_error("Invalid Reference."); 331 | return -EINVAL; 332 | } 333 | 334 | *out_store = static_cast(buffer->get_id()); 335 | return 0; 336 | } 337 | 338 | cros_gralloc_buffer *cros_gralloc_driver::get_buffer(cros_gralloc_handle_t hnd) 339 | { 340 | /* Assumes driver mutex is held. */ 341 | if (handles_.count(hnd)) 342 | return handles_[hnd].first; 343 | 344 | return nullptr; 345 | } 346 | -------------------------------------------------------------------------------- /cros_gralloc/cros_gralloc_driver.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifndef CROS_GRALLOC_DRIVER_H 8 | #define CROS_GRALLOC_DRIVER_H 9 | 10 | #include "cros_gralloc_buffer.h" 11 | 12 | #include 13 | 14 | #include "cros_gralloc_spinlock.h" 15 | 16 | class cros_gralloc_driver 17 | { 18 | public: 19 | cros_gralloc_driver(); 20 | ~cros_gralloc_driver(); 21 | 22 | int32_t init(); 23 | bool is_supported(const struct cros_gralloc_buffer_descriptor *descriptor); 24 | int32_t allocate(const struct cros_gralloc_buffer_descriptor *descriptor, 25 | buffer_handle_t *out_handle); 26 | 27 | int32_t retain(buffer_handle_t handle); 28 | int32_t release(buffer_handle_t handle); 29 | 30 | int32_t lock(buffer_handle_t handle, int32_t acquire_fence, uint32_t map_flags, 31 | uint8_t *addr[DRV_MAX_PLANES]); 32 | int32_t unlock(buffer_handle_t handle, int32_t *release_fence); 33 | 34 | int32_t get_backing_store(buffer_handle_t handle, uint64_t *out_store); 35 | 36 | private: 37 | cros_gralloc_driver(cros_gralloc_driver const &); 38 | cros_gralloc_driver operator=(cros_gralloc_driver const &); 39 | cros_gralloc_buffer *get_buffer(cros_gralloc_handle_t hnd); 40 | 41 | struct driver *drv_; 42 | SpinLock mutex_; 43 | std::unordered_map buffers_; 44 | std::unordered_map> 45 | handles_; 46 | }; 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /cros_gralloc/cros_gralloc_handle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifndef CROS_GRALLOC_HANDLE_H 8 | #define CROS_GRALLOC_HANDLE_H 9 | 10 | #include 11 | #include 12 | 13 | #define DRV_MAX_PLANES 4 14 | 15 | /* 16 | * Only use 32-bit integers in the handle. This guarantees that the handle is 17 | * densely packed (i.e, the compiler does not insert any padding). 18 | */ 19 | 20 | struct cros_gralloc_handle { 21 | native_handle_t base; 22 | int32_t fds[DRV_MAX_PLANES]; 23 | uint32_t strides[DRV_MAX_PLANES]; 24 | uint32_t offsets[DRV_MAX_PLANES]; 25 | uint32_t sizes[DRV_MAX_PLANES]; 26 | uint32_t format_modifiers[2 * DRV_MAX_PLANES]; 27 | uint32_t width; 28 | uint32_t height; 29 | uint32_t format; /* DRM format */ 30 | uint32_t tiling_mode; 31 | uint32_t use_flags[2]; /* Buffer creation flags */ 32 | uint32_t magic; 33 | uint32_t pixel_stride; 34 | int32_t droid_format; 35 | int32_t usage; /* Android usage. */ 36 | uint32_t consumer_usage; 37 | uint32_t producer_usage; 38 | uint32_t yuv_color_range; // YUV Color range. 39 | uint32_t is_updated; // frame updated flag 40 | uint32_t is_encoded; // frame encoded flag 41 | uint32_t is_encrypted; 42 | uint32_t is_key_frame; 43 | uint32_t is_interlaced; 44 | uint32_t is_mmc_capable; 45 | uint32_t compression_mode; 46 | uint32_t compression_hint; 47 | uint32_t codec; 48 | }; 49 | 50 | typedef const struct cros_gralloc_handle *cros_gralloc_handle_t; 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /cros_gralloc/cros_gralloc_helpers.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #include "cros_gralloc_helpers.h" 8 | 9 | #include "i915_private_android.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | const char* drmFormat2Str(int drm_format) 18 | { 19 | static char buf[5]; 20 | char *pDrmFormat = (char*) &drm_format; 21 | snprintf(buf, sizeof(buf), "%c%c%c%c", *pDrmFormat, *(pDrmFormat + 1), 22 | *(pDrmFormat + 2), *(pDrmFormat + 3)); 23 | return buf; 24 | } 25 | 26 | uint32_t cros_gralloc_convert_format(int format) 27 | { 28 | /* 29 | * Conversion from HAL to fourcc-based DRV formats based on 30 | * platform_android.c in mesa. 31 | */ 32 | 33 | switch (format) { 34 | case HAL_PIXEL_FORMAT_BGRA_8888: 35 | return DRM_FORMAT_ARGB8888; 36 | case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: 37 | return DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED; 38 | case HAL_PIXEL_FORMAT_RGB_565: 39 | return DRM_FORMAT_RGB565; 40 | case HAL_PIXEL_FORMAT_RGB_888: 41 | return DRM_FORMAT_RGB888; 42 | case HAL_PIXEL_FORMAT_RGBA_8888: 43 | return DRM_FORMAT_ABGR8888; 44 | case HAL_PIXEL_FORMAT_RGBX_8888: 45 | return DRM_FORMAT_XBGR8888; 46 | case HAL_PIXEL_FORMAT_YCbCr_420_888: 47 | return DRM_FORMAT_FLEX_YCbCr_420_888; 48 | case HAL_PIXEL_FORMAT_YV12: 49 | return DRM_FORMAT_YVU420_ANDROID; 50 | /* 51 | * Choose DRM_FORMAT_R8 because requires the buffers 52 | * with a format HAL_PIXEL_FORMAT_BLOB have a height of 1, and width 53 | * equal to their size in bytes. 54 | */ 55 | case HAL_PIXEL_FORMAT_BLOB: 56 | return DRM_FORMAT_R8; 57 | } 58 | 59 | return i915_private_convert_format(format); 60 | } 61 | 62 | cros_gralloc_handle_t cros_gralloc_convert_handle(buffer_handle_t handle) 63 | { 64 | auto hnd = reinterpret_cast(handle); 65 | if (!hnd || hnd->magic != cros_gralloc_magic) 66 | return nullptr; 67 | 68 | return hnd; 69 | } 70 | 71 | int32_t cros_gralloc_sync_wait(int32_t acquire_fence) 72 | { 73 | if (acquire_fence < 0) 74 | return 0; 75 | 76 | /* 77 | * Wait initially for 1000 ms, and then wait indefinitely. The SYNC_IOC_WAIT 78 | * documentation states the caller waits indefinitely on the fence if timeout < 0. 79 | */ 80 | int err = sync_wait(acquire_fence, 1000); 81 | if (err < 0) { 82 | cros_gralloc_error("Timed out on sync wait, err = %s", strerror(errno)); 83 | err = sync_wait(acquire_fence, -1); 84 | if (err < 0) { 85 | cros_gralloc_error("sync wait error = %s", strerror(errno)); 86 | return -errno; 87 | } 88 | } 89 | 90 | err = close(acquire_fence); 91 | if (err) { 92 | cros_gralloc_error("Unable to close fence fd, err = %s", strerror(errno)); 93 | return -errno; 94 | } 95 | 96 | return 0; 97 | } 98 | 99 | void cros_gralloc_log(const char *prefix, const char *file, int line, const char *format, ...) 100 | { 101 | char buf[50]; 102 | snprintf(buf, sizeof(buf), "[%s:%s(%d)]", prefix, basename(file), line); 103 | 104 | va_list args; 105 | va_start(args, format); 106 | __android_log_vprint(ANDROID_LOG_ERROR, buf, format, args); 107 | va_end(args); 108 | } 109 | 110 | bool is_flex_format(uint32_t format) 111 | { 112 | switch (format) { 113 | case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED: 114 | case DRM_FORMAT_FLEX_YCbCr_420_888: 115 | return true; 116 | default: 117 | return false; 118 | } 119 | return false; 120 | } 121 | -------------------------------------------------------------------------------- /cros_gralloc/cros_gralloc_helpers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifndef CROS_GRALLOC_HELPERS_H 8 | #define CROS_GRALLOC_HELPERS_H 9 | 10 | #include "../drv.h" 11 | #include "cros_gralloc_handle.h" 12 | #include "cros_gralloc_types.h" 13 | 14 | #include 15 | #ifdef USE_VNDK 16 | #include 17 | #else 18 | #include 19 | #endif 20 | 21 | constexpr uint32_t cros_gralloc_magic = 0xABCDDCBA; 22 | constexpr uint32_t handle_data_size = 23 | ((sizeof(struct cros_gralloc_handle) - offsetof(cros_gralloc_handle, fds[0])) / sizeof(int)); 24 | 25 | const char *drmFormat2Str(int format); 26 | uint32_t cros_gralloc_convert_format(int32_t format); 27 | 28 | cros_gralloc_handle_t cros_gralloc_convert_handle(buffer_handle_t handle); 29 | 30 | int32_t cros_gralloc_sync_wait(int32_t acquire_fence); 31 | 32 | bool is_flex_format(uint32_t format); 33 | 34 | __attribute__((format(printf, 4, 5))) void cros_gralloc_log(const char *prefix, const char *file, 35 | int line, const char *format, ...); 36 | 37 | #define cros_gralloc_error(...) \ 38 | do { \ 39 | cros_gralloc_log("CROS_GRALLOC_ERROR", __FILE__, __LINE__, __VA_ARGS__); \ 40 | } while (0) 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /cros_gralloc/cros_gralloc_spinlock.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifndef CROS_GRALLOC_SPINLOCK_H 8 | #define CROS_GRALLOC_SPINLOCK_H 9 | 10 | #include 11 | 12 | #ifndef DISABLE_LOCK 13 | class SpinLock { 14 | public: 15 | void lock() { 16 | while (atomic_lock_.test_and_set(std::memory_order_acquire)) { 17 | } 18 | } 19 | 20 | void unlock() { 21 | atomic_lock_.clear(std::memory_order_release); 22 | } 23 | 24 | private: 25 | std::atomic_flag atomic_lock_ = ATOMIC_FLAG_INIT; 26 | }; 27 | 28 | class ScopedSpinLock { 29 | public: 30 | explicit ScopedSpinLock(SpinLock& lock) : lock_(lock) { 31 | lock_.lock(); 32 | locked_ = true; 33 | } 34 | 35 | ~ScopedSpinLock() { 36 | if (locked_) { 37 | lock_.unlock(); 38 | locked_ = false; 39 | } 40 | } 41 | 42 | private: 43 | SpinLock& lock_; 44 | bool locked_; 45 | }; 46 | 47 | #define SCOPED_SPIN_LOCK(X) \ 48 | ScopedSpinLock lock(X); 49 | #else 50 | class SpinLock { 51 | public: 52 | void lock() { 53 | } 54 | 55 | void unlock() { 56 | } 57 | }; 58 | 59 | #define SCOPED_SPIN_LOCK(X) ((void)0) 60 | #endif 61 | 62 | #endif // PUBLIC_SPINLOCK_H_ 63 | -------------------------------------------------------------------------------- /cros_gralloc/cros_gralloc_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifndef CROS_GRALLOC_TYPES_H 8 | #define CROS_GRALLOC_TYPES_H 9 | 10 | struct cros_gralloc_buffer_descriptor { 11 | uint32_t width; 12 | uint32_t height; 13 | uint32_t consumer_usage; 14 | uint32_t producer_usage; 15 | uint32_t droid_format; 16 | uint32_t drm_format; 17 | uint64_t modifier; 18 | uint64_t use_flags; 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /cros_gralloc/gralloc0/gralloc0.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #include "../cros_gralloc_driver.h" 8 | 9 | #include 10 | #include 11 | 12 | #include "../i915_private_android.h" 13 | #include "../i915_private_android_types.h" 14 | 15 | struct gralloc0_module { 16 | gralloc_module_t base; 17 | std::unique_ptr alloc; 18 | std::unique_ptr driver; 19 | bool initialized; 20 | SpinLock initialization_mutex; 21 | }; 22 | 23 | /* This enumeration must match the one in . 24 | * The functions supported by this gralloc's temporary private API are listed 25 | * below. Use of these functions is highly discouraged and should only be 26 | * reserved for cases where no alternative to get same information (such as 27 | * querying ANativeWindow) exists. 28 | */ 29 | // clang-format off 30 | enum { 31 | GRALLOC_DRM_GET_STRIDE, 32 | GRALLOC_DRM_GET_FORMAT, 33 | GRALLOC_DRM_GET_DIMENSIONS, 34 | GRALLOC_DRM_GET_BACKING_STORE, 35 | }; 36 | // clang-format on 37 | 38 | static uint64_t gralloc0_convert_usage(int usage) 39 | { 40 | uint64_t use_flags = BO_USE_NONE; 41 | 42 | if (usage & GRALLOC_USAGE_CURSOR) 43 | use_flags |= BO_USE_CURSOR; 44 | if ((usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_RARELY) 45 | use_flags |= BO_USE_SW_READ_RARELY; 46 | if ((usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN) 47 | use_flags |= BO_USE_SW_READ_OFTEN; 48 | if ((usage & GRALLOC_USAGE_SW_WRITE_MASK) == GRALLOC_USAGE_SW_WRITE_RARELY) 49 | use_flags |= BO_USE_SW_WRITE_RARELY; 50 | if ((usage & GRALLOC_USAGE_SW_WRITE_MASK) == GRALLOC_USAGE_SW_WRITE_OFTEN) 51 | use_flags |= BO_USE_SW_WRITE_OFTEN; 52 | if (usage & GRALLOC_USAGE_HW_TEXTURE) 53 | use_flags |= BO_USE_TEXTURE; 54 | if (usage & GRALLOC_USAGE_HW_RENDER) 55 | use_flags |= BO_USE_RENDERING; 56 | if (usage & GRALLOC_USAGE_HW_2D) 57 | use_flags |= BO_USE_RENDERING; 58 | if (usage & GRALLOC_USAGE_HW_COMPOSER) 59 | /* HWC wants to use display hardware, but can defer to OpenGL. */ 60 | use_flags |= BO_USE_SCANOUT | BO_USE_TEXTURE; 61 | if (usage & GRALLOC_USAGE_HW_FB) 62 | use_flags |= BO_USE_NONE; 63 | if (usage & GRALLOC_USAGE_EXTERNAL_DISP) 64 | /* 65 | * This flag potentially covers external display for the normal drivers (i915, 66 | * rockchip) and usb monitors (evdi/udl). It's complicated so ignore it. 67 | * */ 68 | use_flags |= BO_USE_NONE; 69 | if (usage & GRALLOC_USAGE_PROTECTED) 70 | use_flags |= BO_USE_PROTECTED; 71 | if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) 72 | /*HACK: See b/30054495 */ 73 | use_flags |= BO_USE_SW_READ_OFTEN; 74 | if (usage & GRALLOC_USAGE_HW_CAMERA_WRITE) 75 | use_flags |= BO_USE_CAMERA_WRITE; 76 | if (usage & GRALLOC_USAGE_HW_CAMERA_READ) 77 | use_flags |= BO_USE_CAMERA_READ; 78 | if (usage & GRALLOC_USAGE_RENDERSCRIPT) 79 | use_flags |= BO_USE_RENDERSCRIPT; 80 | 81 | return use_flags; 82 | } 83 | 84 | static uint32_t gralloc0_convert_map_usage(int map_usage) 85 | { 86 | uint32_t map_flags = BO_MAP_NONE; 87 | 88 | if (map_usage & GRALLOC_USAGE_SW_READ_MASK) 89 | map_flags |= BO_MAP_READ; 90 | if (map_usage & GRALLOC_USAGE_SW_WRITE_MASK) 91 | map_flags |= BO_MAP_WRITE; 92 | 93 | return map_flags; 94 | } 95 | 96 | static int gralloc0_alloc(alloc_device_t *dev, int w, int h, int format, int usage, 97 | buffer_handle_t *handle, int *stride) 98 | { 99 | int32_t ret; 100 | bool supported; 101 | struct cros_gralloc_buffer_descriptor descriptor; 102 | auto mod = (struct gralloc0_module *)dev->common.module; 103 | 104 | descriptor.width = w; 105 | descriptor.height = h; 106 | descriptor.droid_format = format; 107 | descriptor.producer_usage = descriptor.consumer_usage = usage; 108 | descriptor.modifier = 0; 109 | descriptor.drm_format = cros_gralloc_convert_format(format); 110 | descriptor.use_flags = gralloc0_convert_usage(usage); 111 | 112 | supported = mod->driver->is_supported(&descriptor); 113 | if (!supported && (usage & GRALLOC_USAGE_HW_COMPOSER)) { 114 | descriptor.use_flags &= ~BO_USE_SCANOUT; 115 | supported = mod->driver->is_supported(&descriptor); 116 | } 117 | 118 | if (!supported) { 119 | cros_gralloc_error("Unsupported combination -- HAL format: %u, HAL usage: %u, " 120 | "drv_format: %4.4s, use_flags: %llu", 121 | format, usage, drmFormat2Str(descriptor.drm_format), 122 | static_cast(descriptor.use_flags)); 123 | return -EINVAL; 124 | } 125 | 126 | ret = mod->driver->allocate(&descriptor, handle); 127 | if (ret) 128 | return ret; 129 | 130 | auto hnd = cros_gralloc_convert_handle(*handle); 131 | *stride = hnd->pixel_stride; 132 | 133 | return 0; 134 | } 135 | 136 | static int gralloc0_free(alloc_device_t *dev, buffer_handle_t handle) 137 | { 138 | auto mod = (struct gralloc0_module *)dev->common.module; 139 | return mod->driver->release(handle); 140 | } 141 | 142 | static int gralloc0_close(struct hw_device_t *dev) 143 | { 144 | /* Memory is freed by managed pointers on process close. */ 145 | return 0; 146 | } 147 | 148 | static int gralloc0_init(struct gralloc0_module *mod, bool initialize_alloc) 149 | { 150 | SCOPED_SPIN_LOCK(mod->initialization_mutex); 151 | 152 | if (mod->initialized) 153 | return 0; 154 | 155 | mod->driver = std::make_unique(); 156 | if (mod->driver->init()) { 157 | cros_gralloc_error("Failed to initialize driver."); 158 | return -ENODEV; 159 | } 160 | 161 | if (initialize_alloc) { 162 | mod->alloc = std::make_unique(); 163 | mod->alloc->alloc = gralloc0_alloc; 164 | mod->alloc->free = gralloc0_free; 165 | mod->alloc->common.tag = HARDWARE_DEVICE_TAG; 166 | mod->alloc->common.version = 0; 167 | mod->alloc->common.module = (hw_module_t *)mod; 168 | mod->alloc->common.close = gralloc0_close; 169 | } 170 | 171 | mod->initialized = true; 172 | return 0; 173 | } 174 | 175 | static int gralloc0_open(const struct hw_module_t *mod, const char *name, struct hw_device_t **dev) 176 | { 177 | auto module = (struct gralloc0_module *)mod; 178 | 179 | if (module->initialized) { 180 | *dev = &module->alloc->common; 181 | return 0; 182 | } 183 | 184 | /* On Android M, Surfaceflinger tries to open the gralloc device 185 | * using name GRALLOC_HARDWARE_FB0. 186 | */ 187 | if ((strcmp(name, GRALLOC_HARDWARE_GPU0)!=0) && (strcmp(name, GRALLOC_HARDWARE_FB0)!=0)) { 188 | cros_gralloc_error("Incorrect device name - %s.", name); 189 | return -EINVAL; 190 | } 191 | 192 | if (gralloc0_init(module, true)) 193 | return -ENODEV; 194 | 195 | *dev = &module->alloc->common; 196 | return 0; 197 | } 198 | 199 | static int gralloc0_register_buffer(struct gralloc_module_t const *module, buffer_handle_t handle) 200 | { 201 | auto mod = (struct gralloc0_module *)module; 202 | 203 | if (!mod->initialized) 204 | if (gralloc0_init(mod, false)) 205 | return -ENODEV; 206 | 207 | return mod->driver->retain(handle); 208 | } 209 | 210 | static int gralloc0_unregister_buffer(struct gralloc_module_t const *module, buffer_handle_t handle) 211 | { 212 | auto mod = (struct gralloc0_module *)module; 213 | return mod->driver->release(handle); 214 | } 215 | 216 | static int gralloc0_lock(struct gralloc_module_t const *module, buffer_handle_t handle, int usage, 217 | int l, int t, int w, int h, void **vaddr) 218 | { 219 | return module->lockAsync(module, handle, usage, l, t, w, h, vaddr, -1); 220 | } 221 | 222 | static int gralloc0_unlock(struct gralloc_module_t const *module, buffer_handle_t handle) 223 | { 224 | int32_t fence_fd, ret; 225 | auto mod = (struct gralloc0_module *)module; 226 | ret = mod->driver->unlock(handle, &fence_fd); 227 | if (ret) 228 | return ret; 229 | 230 | ret = cros_gralloc_sync_wait(fence_fd); 231 | if (ret) 232 | return ret; 233 | 234 | return 0; 235 | } 236 | 237 | static int gralloc0_perform(struct gralloc_module_t const *module, int op, ...) 238 | { 239 | va_list args; 240 | int32_t *out_format, ret; 241 | uint64_t *out_store; 242 | buffer_handle_t handle; 243 | uint32_t *out_width, *out_height, *out_stride; 244 | auto mod = (struct gralloc0_module *)module; 245 | 246 | switch (op) { 247 | case GRALLOC_DRM_GET_STRIDE: 248 | case GRALLOC_DRM_GET_FORMAT: 249 | case GRALLOC_DRM_GET_DIMENSIONS: 250 | case GRALLOC_DRM_GET_BACKING_STORE: 251 | break; 252 | default: 253 | return -EINVAL; 254 | } 255 | 256 | va_start(args, op); 257 | 258 | ret = 0; 259 | handle = va_arg(args, buffer_handle_t); 260 | auto hnd = cros_gralloc_convert_handle(handle); 261 | if (!hnd) { 262 | cros_gralloc_error("Invalid handle."); 263 | return -EINVAL; 264 | } 265 | 266 | switch (op) { 267 | case GRALLOC_DRM_GET_STRIDE: 268 | out_stride = va_arg(args, uint32_t *); 269 | *out_stride = hnd->pixel_stride; 270 | break; 271 | case GRALLOC_DRM_GET_FORMAT: 272 | out_format = va_arg(args, int32_t *); 273 | *out_format = hnd->droid_format; 274 | break; 275 | case GRALLOC_DRM_GET_DIMENSIONS: 276 | out_width = va_arg(args, uint32_t *); 277 | out_height = va_arg(args, uint32_t *); 278 | *out_width = hnd->width; 279 | *out_height = hnd->height; 280 | break; 281 | case GRALLOC_DRM_GET_BACKING_STORE: 282 | out_store = va_arg(args, uint64_t *); 283 | ret = mod->driver->get_backing_store(handle, out_store); 284 | break; 285 | default: 286 | ret = -EINVAL; 287 | } 288 | 289 | va_end(args); 290 | 291 | return ret; 292 | } 293 | 294 | static int gralloc0_lock_ycbcr(struct gralloc_module_t const *module, buffer_handle_t handle, 295 | int usage, int l, int t, int w, int h, struct android_ycbcr *ycbcr) 296 | { 297 | return module->lockAsync_ycbcr(module, handle, usage, l, t, w, h, ycbcr, -1); 298 | } 299 | 300 | static int gralloc0_lock_async(struct gralloc_module_t const *module, buffer_handle_t handle, 301 | int usage, int l, int t, int w, int h, void **vaddr, int fence_fd) 302 | { 303 | int32_t ret; 304 | uint32_t map_flags; 305 | uint8_t *addr[DRV_MAX_PLANES]; 306 | auto mod = (struct gralloc0_module *)module; 307 | 308 | auto hnd = cros_gralloc_convert_handle(handle); 309 | if (!hnd) { 310 | cros_gralloc_error("Invalid handle."); 311 | return -EINVAL; 312 | } 313 | 314 | if (hnd->droid_format == HAL_PIXEL_FORMAT_YCbCr_420_888) { 315 | cros_gralloc_error("HAL_PIXEL_FORMAT_YCbCr_*_888 format not compatible."); 316 | return -EINVAL; 317 | } 318 | 319 | map_flags = gralloc0_convert_map_usage(usage); 320 | ret = mod->driver->lock(handle, fence_fd, map_flags, addr); 321 | *vaddr = addr[0]; 322 | return ret; 323 | } 324 | 325 | static int gralloc0_unlock_async(struct gralloc_module_t const *module, buffer_handle_t handle, 326 | int *fence_fd) 327 | { 328 | auto mod = (struct gralloc0_module *)module; 329 | return mod->driver->unlock(handle, fence_fd); 330 | } 331 | 332 | static int gralloc0_lock_async_ycbcr(struct gralloc_module_t const *module, buffer_handle_t handle, 333 | int usage, int l, int t, int w, int h, 334 | struct android_ycbcr *ycbcr, int fence_fd) 335 | { 336 | int32_t ret; 337 | uint32_t map_flags; 338 | uint8_t *addr[DRV_MAX_PLANES] = { nullptr, nullptr, nullptr, nullptr }; 339 | auto mod = (struct gralloc0_module *)module; 340 | 341 | auto hnd = cros_gralloc_convert_handle(handle); 342 | if (!hnd) { 343 | cros_gralloc_error("Invalid handle."); 344 | return -EINVAL; 345 | } 346 | 347 | if ((hnd->droid_format != HAL_PIXEL_FORMAT_YCbCr_420_888) && 348 | (hnd->droid_format != HAL_PIXEL_FORMAT_YV12) && 349 | (hnd->droid_format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) && 350 | !i915_private_supported_yuv_format(hnd->droid_format)) { 351 | cros_gralloc_error("Non-YUV format not compatible."); 352 | return -EINVAL; 353 | } 354 | 355 | map_flags = gralloc0_convert_map_usage(usage); 356 | ret = mod->driver->lock(handle, fence_fd, map_flags, addr); 357 | if (ret) 358 | return ret; 359 | 360 | switch (hnd->format) { 361 | case DRM_FORMAT_NV12: 362 | case DRM_FORMAT_NV12_Y_TILED_INTEL: 363 | ycbcr->y = addr[0]; 364 | ycbcr->cb = addr[1]; 365 | ycbcr->cr = addr[1] + 1; 366 | ycbcr->ystride = hnd->strides[0]; 367 | ycbcr->cstride = hnd->strides[1]; 368 | ycbcr->chroma_step = 2; 369 | break; 370 | case DRM_FORMAT_YVU420: 371 | case DRM_FORMAT_YVU420_ANDROID: 372 | ycbcr->y = addr[0]; 373 | ycbcr->cb = addr[2]; 374 | ycbcr->cr = addr[1]; 375 | ycbcr->ystride = hnd->strides[0]; 376 | ycbcr->cstride = hnd->strides[1]; 377 | ycbcr->chroma_step = 1; 378 | break; 379 | default: 380 | module->unlock(module, handle); 381 | return -EINVAL; 382 | } 383 | 384 | return 0; 385 | } 386 | 387 | // clang-format off 388 | static struct hw_module_methods_t gralloc0_module_methods = { .open = gralloc0_open }; 389 | // clang-format on 390 | 391 | struct gralloc0_module HAL_MODULE_INFO_SYM = { 392 | .base = 393 | { 394 | .common = 395 | { 396 | .tag = HARDWARE_MODULE_TAG, 397 | .module_api_version = GRALLOC_MODULE_API_VERSION_0_3, 398 | .hal_api_version = 0, 399 | .id = GRALLOC_HARDWARE_MODULE_ID, 400 | .name = "CrOS Gralloc", 401 | .author = "Chrome OS", 402 | .methods = &gralloc0_module_methods, 403 | }, 404 | 405 | .registerBuffer = gralloc0_register_buffer, 406 | .unregisterBuffer = gralloc0_unregister_buffer, 407 | .lock = gralloc0_lock, 408 | .unlock = gralloc0_unlock, 409 | .perform = gralloc0_perform, 410 | .lock_ycbcr = gralloc0_lock_ycbcr, 411 | .lockAsync = gralloc0_lock_async, 412 | .unlockAsync = gralloc0_unlock_async, 413 | .lockAsync_ycbcr = gralloc0_lock_async_ycbcr, 414 | }, 415 | 416 | .alloc = nullptr, 417 | .driver = nullptr, 418 | .initialized = false, 419 | }; 420 | -------------------------------------------------------------------------------- /cros_gralloc/gralloc0/tests/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2016 The Chromium OS Authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style license that can be 3 | # found in the LICENSE file. 4 | 5 | GRALLOCTEST = gralloctest 6 | SOURCES += gralloctest.c 7 | 8 | CCFLAGS += -g -O2 -Wall -fPIE 9 | LIBS += -lhardware -lsync -lcutils -pie 10 | 11 | OBJS = $(foreach source, $(SOURCES), $(addsuffix .o, $(basename $(source)))) 12 | 13 | OBJECTS = $(addprefix $(TARGET_DIR), $(notdir $(OBJS))) 14 | BINARY = $(addprefix $(TARGET_DIR), $(GRALLOCTEST)) 15 | 16 | .PHONY: all clean 17 | 18 | all: $(BINARY) 19 | 20 | $(BINARY): $(OBJECTS) 21 | 22 | clean: 23 | $(RM) $(BINARY) 24 | $(RM) $(OBJECTS) 25 | 26 | $(BINARY): 27 | $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS) 28 | 29 | $(TARGET_DIR)%.o: %.c 30 | $(CC) $(CFLAGS) -c $^ -o $@ -MMD 31 | -------------------------------------------------------------------------------- /cros_gralloc/gralloc1/cros_gralloc1_module.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef CROS_GRALLOC1_MODULE_H 18 | #define CROS_GRALLOC1_MODULE_H 19 | 20 | #include 21 | 22 | #include "../cros_gralloc_driver.h" 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | struct cros_gralloc_module; 29 | 30 | namespace android 31 | { 32 | 33 | typedef enum { 34 | CROS_GRALLOC_ERROR_NONE = 0, 35 | CROS_GRALLOC_ERROR_BAD_DESCRIPTOR = 1, 36 | CROS_GRALLOC_ERROR_BAD_HANDLE = 2, 37 | CROS_GRALLOC_ERROR_BAD_VALUE = 3, 38 | CROS_GRALLOC_ERROR_NOT_SHARED = 4, 39 | CROS_GRALLOC_ERROR_NO_RESOURCES = 5, 40 | CROS_GRALLOC_ERROR_UNDEFINED = 6, 41 | CROS_GRALLOC_ERROR_UNSUPPORTED = 7, 42 | } cros_gralloc_error_t; 43 | 44 | class CrosGralloc1 : public gralloc1_device_t 45 | { 46 | public: 47 | CrosGralloc1(); 48 | ~CrosGralloc1(); 49 | 50 | bool Init(); 51 | 52 | static int HookDevOpen(const struct hw_module_t *mod, const char *name, 53 | struct hw_device_t **device); 54 | static int HookDevClose(hw_device_t *dev); 55 | 56 | private: 57 | static inline CrosGralloc1 *getAdapter(gralloc1_device_t *device) 58 | { 59 | return static_cast(device); 60 | } 61 | 62 | // getCapabilities 63 | 64 | void doGetCapabilities(uint32_t *outCount, 65 | int32_t * /*gralloc1_capability_t*/ outCapabilities); 66 | static void getCapabilitiesHook(gralloc1_device_t *device, uint32_t *outCount, 67 | int32_t * /*gralloc1_capability_t*/ outCapabilities) 68 | { 69 | getAdapter(device)->doGetCapabilities(outCount, outCapabilities); 70 | }; 71 | 72 | // getFunction 73 | 74 | gralloc1_function_pointer_t 75 | doGetFunction(int32_t /*gralloc1_function_descriptor_t*/ descriptor); 76 | static gralloc1_function_pointer_t 77 | getFunctionHook(gralloc1_device_t *device, 78 | int32_t /*gralloc1_function_descriptor_t*/ descriptor) 79 | { 80 | return getAdapter(device)->doGetFunction(descriptor); 81 | } 82 | 83 | // dump 84 | 85 | void dump(uint32_t *outSize, char *outBuffer); 86 | static void dumpHook(gralloc1_device_t *device, uint32_t *outSize, char *outBuffer) 87 | { 88 | return getAdapter(device)->dump(outSize, outBuffer); 89 | } 90 | 91 | // Buffer descriptor functions 92 | 93 | int32_t setConsumerUsage(gralloc1_buffer_descriptor_t descriptorId, uint64_t intUsage); 94 | 95 | int32_t setProducerUsage(gralloc1_buffer_descriptor_t descriptorId, uint64_t intUsage); 96 | 97 | int32_t setDimensions(gralloc1_buffer_descriptor_t descriptorId, uint32_t width, 98 | uint32_t height); 99 | 100 | int32_t setFormat(gralloc1_buffer_descriptor_t descriptorId, int32_t format); 101 | int32_t setInterlace(buffer_handle_t buffer, uint32_t interlace); 102 | int32_t setProtectionInfo(buffer_handle_t buffer, uint32_t protection_info); 103 | 104 | int32_t createDescriptor(gralloc1_buffer_descriptor_t *outDescriptor); 105 | static int32_t createDescriptorHook(gralloc1_device_t *device, 106 | gralloc1_buffer_descriptor_t *outDescriptor) 107 | { 108 | return getAdapter(device)->createDescriptor(outDescriptor); 109 | } 110 | 111 | int32_t destroyDescriptor(gralloc1_buffer_descriptor_t descriptor); 112 | static int32_t destroyDescriptorHook(gralloc1_device_t *device, 113 | gralloc1_buffer_descriptor_t descriptor) 114 | { 115 | return getAdapter(device)->destroyDescriptor(descriptor); 116 | } 117 | 118 | static int32_t setConsumerUsageHook(gralloc1_device_t *device, 119 | gralloc1_buffer_descriptor_t descriptorId, 120 | uint64_t intUsage) 121 | { 122 | return getAdapter(device)->setConsumerUsage(descriptorId, intUsage); 123 | } 124 | 125 | static int32_t setDimensionsHook(gralloc1_device_t *device, 126 | gralloc1_buffer_descriptor_t descriptorId, uint32_t width, 127 | uint32_t height) 128 | { 129 | return getAdapter(device)->setDimensions(descriptorId, width, height); 130 | } 131 | 132 | static int32_t setFormatHook(gralloc1_device_t *device, 133 | gralloc1_buffer_descriptor_t descriptorId, int32_t format) 134 | { 135 | return getAdapter(device)->setFormat(descriptorId, format); 136 | } 137 | 138 | static int32_t setInterlaceHook(gralloc1_device_t *device, 139 | buffer_handle_t buffer, uint32_t interlace) 140 | { 141 | return getAdapter(device)->setInterlace(buffer, interlace); 142 | } 143 | 144 | static int32_t setProtectionInfoHook(gralloc1_device_t *device, 145 | buffer_handle_t buffer, uint32_t protection_info) 146 | { 147 | return getAdapter(device)->setProtectionInfo(buffer, protection_info); 148 | } 149 | 150 | static int32_t setProducerUsageHook(gralloc1_device_t *device, 151 | gralloc1_buffer_descriptor_t descriptorId, 152 | uint64_t intUsage) 153 | { 154 | return getAdapter(device)->setProducerUsage(descriptorId, intUsage); 155 | } 156 | 157 | int32_t getNumFlexPlanes(buffer_handle_t buffer, uint32_t *outNumPlanes); 158 | static int32_t getNumFlexPlanesHook(gralloc1_device_t *device, buffer_handle_t buffer, 159 | uint32_t *outNumPlanes) 160 | { 161 | return getAdapter(device)->getNumFlexPlanes(buffer, outNumPlanes); 162 | } 163 | 164 | int32_t getBackingStore(buffer_handle_t buffer, gralloc1_backing_store_t *outStore); 165 | static int32_t getBackingStoreHook(gralloc1_device_t *device, buffer_handle_t buffer, 166 | gralloc1_backing_store_t *outStore) 167 | { 168 | return getAdapter(device)->getBackingStore(buffer, outStore); 169 | } 170 | 171 | int32_t getConsumerUsage(buffer_handle_t buffer, 172 | uint64_t * /*gralloc1_consumer_usage_t*/ outUsage); 173 | static int32_t getConsumerUsageHook(gralloc1_device_t *device, buffer_handle_t buffer, 174 | uint64_t * /*gralloc1_consumer_usage_t*/ outUsage) 175 | { 176 | return getAdapter(device)->getConsumerUsage(buffer, outUsage); 177 | } 178 | 179 | int32_t getDimensions(buffer_handle_t buffer, uint32_t *outWidth, uint32_t *outHeight); 180 | static int32_t getDimensionsHook(gralloc1_device_t *device, buffer_handle_t buffer, 181 | uint32_t *outWidth, uint32_t *outHeight) 182 | { 183 | return getAdapter(device)->getDimensions(buffer, outWidth, outHeight); 184 | } 185 | 186 | int32_t getFormat(buffer_handle_t buffer, int32_t *outFormat); 187 | static int32_t getFormatHook(gralloc1_device_t *device, buffer_handle_t buffer, 188 | int32_t *outFormat) 189 | { 190 | return getAdapter(device)->getFormat(buffer, outFormat); 191 | } 192 | 193 | int32_t validateBufferSize(buffer_handle_t buffer, 194 | const gralloc1_buffer_descriptor_info_t *descriptorInfo, 195 | uint32_t stride); 196 | static int32_t 197 | validateBufferSizeHook(gralloc1_device_t *device, buffer_handle_t buffer, 198 | const gralloc1_buffer_descriptor_info_t *descriptorInfo, 199 | uint32_t stride) 200 | { 201 | return getAdapter(device)->validateBufferSize(buffer, descriptorInfo, stride); 202 | } 203 | 204 | int32_t getTransportSize(buffer_handle_t buffer, uint32_t *outNumFds, uint32_t *outNumInts); 205 | static int32_t getTransportSizeHook(gralloc1_device_t *device, buffer_handle_t buffer, 206 | uint32_t *outNumFds, uint32_t *outNumInts) 207 | { 208 | return getAdapter(device)->getTransportSize(buffer, outNumFds, outNumInts); 209 | } 210 | 211 | int32_t importBuffer(const buffer_handle_t rawHandle, buffer_handle_t *outBuffer); 212 | static int32_t importBufferHook(gralloc1_device_t *device, const buffer_handle_t rawHandle, 213 | buffer_handle_t *outBuffer) 214 | { 215 | return getAdapter(device)->importBuffer(rawHandle, outBuffer); 216 | } 217 | 218 | int32_t getProducerUsage(buffer_handle_t buffer, 219 | uint64_t * /*gralloc1_producer_usage_t*/ outUsage); 220 | static int32_t getProducerUsageHook(gralloc1_device_t *device, buffer_handle_t buffer, 221 | uint64_t * /*gralloc1_producer_usage_t*/ outUsage) 222 | { 223 | return getAdapter(device)->getProducerUsage(buffer, outUsage); 224 | } 225 | 226 | int32_t getStride(buffer_handle_t buffer, uint32_t *outStride); 227 | static int32_t getStrideHook(gralloc1_device_t *device, buffer_handle_t buffer, 228 | uint32_t *outStride) 229 | { 230 | return getAdapter(device)->getStride(buffer, outStride); 231 | } 232 | 233 | int32_t getPrime(buffer_handle_t buffer, uint32_t *prime); 234 | static int32_t getPrimeHook(gralloc1_device_t *device, buffer_handle_t buffer, 235 | uint32_t *prime) 236 | { 237 | return getAdapter(device)->getPrime(buffer, prime); 238 | } 239 | 240 | int32_t getByteStride(buffer_handle_t buffer, uint32_t *outStride, uint32_t size); 241 | static int32_t getByteStrideHook(gralloc1_device_t *device, buffer_handle_t buffer, 242 | uint32_t *outStride, uint32_t size) 243 | { 244 | return getAdapter(device)->getByteStride(buffer, outStride, size); 245 | } 246 | 247 | // Buffer Management functions 248 | int32_t allocate(struct cros_gralloc_buffer_descriptor *descriptor, 249 | buffer_handle_t *outBufferHandle); 250 | static int32_t allocateBuffers(gralloc1_device_t *device, uint32_t numDescriptors, 251 | const gralloc1_buffer_descriptor_t *descriptors, 252 | buffer_handle_t *outBuffers); 253 | 254 | int32_t release(buffer_handle_t bufferHandle); 255 | int32_t retain(buffer_handle_t bufferHandle); 256 | 257 | // Member function pointer 'member' will either be retain or release 258 | template 259 | static int32_t managementHook(gralloc1_device_t *device, buffer_handle_t bufferHandle) 260 | { 261 | auto adapter = getAdapter(device); 262 | return ((*adapter).*member)(bufferHandle); 263 | } 264 | 265 | // Buffer access functions 266 | int32_t lock(buffer_handle_t bufferHandle, gralloc1_producer_usage_t producerUsage, 267 | gralloc1_consumer_usage_t consumerUsage, const gralloc1_rect_t &accessRegion, 268 | void **outData, int32_t acquireFence); 269 | int32_t lockFlex(buffer_handle_t bufferHandle, gralloc1_producer_usage_t producerUsage, 270 | gralloc1_consumer_usage_t consumerUsage, 271 | const gralloc1_rect_t &accessRegion, struct android_flex_layout *outFlex, 272 | int32_t acquireFence); 273 | int32_t lockYCbCr(buffer_handle_t bufferHandle, gralloc1_producer_usage_t producerUsage, 274 | gralloc1_consumer_usage_t consumerUsage, 275 | const gralloc1_rect_t &accessRegion, struct android_ycbcr *outFlex, 276 | int32_t acquireFence); 277 | 278 | template 282 | static int32_t lockHook(gralloc1_device_t *device, buffer_handle_t bufferHandle, 283 | uint64_t /*gralloc1_producer_usage_t*/ uintProducerUsage, 284 | uint64_t /*gralloc1_consumer_usage_t*/ uintConsumerUsage, 285 | const gralloc1_rect_t *accessRegion, OUT *outData, 286 | int32_t acquireFenceFd) 287 | { 288 | auto adapter = getAdapter(device); 289 | 290 | // Exactly one of producer and consumer usage must be *_USAGE_NONE, 291 | // but we can't check this until the upper levels of the framework 292 | // correctly distinguish between producer and consumer usage 293 | /* 294 | bool hasProducerUsage = 295 | uintProducerUsage != GRALLOC1_PRODUCER_USAGE_NONE; 296 | bool hasConsumerUsage = 297 | uintConsumerUsage != GRALLOC1_CONSUMER_USAGE_NONE; 298 | if (hasProducerUsage && hasConsumerUsage || 299 | !hasProducerUsage && !hasConsumerUsage) { 300 | return static_cast(GRALLOC1_ERROR_BAD_VALUE); 301 | } 302 | */ 303 | 304 | auto producerUsage = static_cast(uintProducerUsage); 305 | auto consumerUsage = static_cast(uintConsumerUsage); 306 | 307 | if (!outData) { 308 | const auto producerCpuUsage = 309 | GRALLOC1_PRODUCER_USAGE_CPU_READ | GRALLOC1_PRODUCER_USAGE_CPU_WRITE; 310 | if (producerUsage & (producerCpuUsage != 0)) { 311 | return CROS_GRALLOC_ERROR_BAD_VALUE; 312 | } 313 | if (consumerUsage & (GRALLOC1_CONSUMER_USAGE_CPU_READ != 0)) { 314 | return CROS_GRALLOC_ERROR_BAD_VALUE; 315 | } 316 | } 317 | 318 | if (!accessRegion) { 319 | ALOGE("accessRegion is null"); 320 | return CROS_GRALLOC_ERROR_BAD_VALUE; 321 | } 322 | 323 | return ((*adapter).*member)(bufferHandle, producerUsage, consumerUsage, 324 | *accessRegion, outData, acquireFenceFd); 325 | } 326 | 327 | int32_t unlock(buffer_handle_t bufferHandle, int32_t *outReleaseFence); 328 | static int32_t unlockHook(gralloc1_device_t *device, buffer_handle_t bufferHandle, 329 | int32_t *outReleaseFenceFd) 330 | { 331 | auto adapter = getAdapter(device); 332 | *outReleaseFenceFd = -1; 333 | int32_t releaseFence; 334 | auto error = adapter->unlock(bufferHandle, &releaseFence); 335 | if (error == CROS_GRALLOC_ERROR_NONE && releaseFence > 0) { 336 | *outReleaseFenceFd = dup(releaseFence); 337 | } 338 | return error; 339 | } 340 | 341 | int32_t setModifier(gralloc1_buffer_descriptor_t descriptor, uint64_t modifier); 342 | static int32_t setModifierHook(gralloc1_device_t *device, 343 | gralloc1_buffer_descriptor_t descriptor, uint64_t modifier) 344 | { 345 | return getAdapter(device)->setModifier(descriptor, modifier); 346 | } 347 | 348 | // Adapter internals 349 | std::unique_ptr driver; 350 | }; 351 | 352 | } // namespace android 353 | 354 | #endif 355 | -------------------------------------------------------------------------------- /cros_gralloc/i915_private_android.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifdef DRV_I915 8 | 9 | #include "i915_private_android.h" 10 | #include "i915_private_android_types.h" 11 | 12 | #include "cros_gralloc_helpers.h" 13 | 14 | #include 15 | 16 | uint32_t i915_private_convert_format(int format) 17 | { 18 | switch (format) { 19 | case HAL_PIXEL_FORMAT_NV12: 20 | return DRM_FORMAT_NV12; 21 | case HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL: 22 | return DRM_FORMAT_NV12_Y_TILED_INTEL; 23 | case HAL_PIXEL_FORMAT_YCbCr_422_I: 24 | return DRM_FORMAT_YUYV; 25 | case HAL_PIXEL_FORMAT_Y16: 26 | return DRM_FORMAT_R16; 27 | case HAL_PIXEL_FORMAT_YCbCr_444_888: 28 | return DRM_FORMAT_YUV444; 29 | case HAL_PIXEL_FORMAT_YCrCb_420_SP: 30 | return DRM_FORMAT_NV21; 31 | case HAL_PIXEL_FORMAT_YCbCr_422_SP: 32 | return DRM_FORMAT_NV16; 33 | case HAL_PIXEL_FORMAT_YCbCr_422_888: 34 | return DRM_FORMAT_YUV422; 35 | case HAL_PIXEL_FORMAT_P010_INTEL: 36 | return DRM_FORMAT_P010; 37 | case HAL_PIXEL_FORMAT_RGBA_1010102: 38 | return DRM_FORMAT_ABGR2101010; 39 | case HAL_PIXEL_FORMAT_RGBA_FP16: 40 | return DRM_FORMAT_ABGR16161616F; 41 | } 42 | 43 | return DRM_FORMAT_NONE; 44 | } 45 | 46 | int32_t i915_private_invert_format(int format) 47 | { 48 | /* Convert the DRM FourCC into the most specific HAL pixel format. */ 49 | switch (format) { 50 | case DRM_FORMAT_ARGB8888: 51 | return HAL_PIXEL_FORMAT_BGRA_8888; 52 | case DRM_FORMAT_RGB565: 53 | return HAL_PIXEL_FORMAT_RGB_565; 54 | case DRM_FORMAT_RGB888: 55 | return HAL_PIXEL_FORMAT_RGB_888; 56 | case DRM_FORMAT_ABGR8888: 57 | return HAL_PIXEL_FORMAT_RGBA_8888; 58 | case DRM_FORMAT_XBGR8888: 59 | return HAL_PIXEL_FORMAT_RGBX_8888; 60 | case DRM_FORMAT_FLEX_YCbCr_420_888: 61 | return HAL_PIXEL_FORMAT_YCbCr_420_888; 62 | case DRM_FORMAT_YVU420_ANDROID: 63 | return HAL_PIXEL_FORMAT_YV12; 64 | case DRM_FORMAT_R8: 65 | return HAL_PIXEL_FORMAT_BLOB; 66 | case DRM_FORMAT_NV12: 67 | return HAL_PIXEL_FORMAT_NV12; 68 | case DRM_FORMAT_NV12_Y_TILED_INTEL: 69 | return HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL; 70 | case DRM_FORMAT_YUYV: 71 | return HAL_PIXEL_FORMAT_YCbCr_422_I; 72 | case DRM_FORMAT_R16: 73 | return HAL_PIXEL_FORMAT_Y16; 74 | case DRM_FORMAT_P010: 75 | return HAL_PIXEL_FORMAT_P010_INTEL; 76 | case DRM_FORMAT_YUV444: 77 | return HAL_PIXEL_FORMAT_YCbCr_444_888; 78 | case DRM_FORMAT_NV21: 79 | return HAL_PIXEL_FORMAT_YCrCb_420_SP; 80 | case DRM_FORMAT_NV16: 81 | return HAL_PIXEL_FORMAT_YCbCr_422_SP; 82 | case DRM_FORMAT_YUV422: 83 | return HAL_PIXEL_FORMAT_YCbCr_422_888; 84 | case DRM_FORMAT_ABGR2101010: 85 | return HAL_PIXEL_FORMAT_RGBA_1010102; 86 | case DRM_FORMAT_ABGR16161616F: 87 | return HAL_PIXEL_FORMAT_RGBA_FP16; 88 | default: 89 | cros_gralloc_error("Unhandled DRM format %4.4s", drmFormat2Str(format)); 90 | } 91 | 92 | return 0; 93 | } 94 | 95 | bool i915_private_supported_yuv_format(uint32_t droid_format) 96 | { 97 | switch (droid_format) { 98 | case HAL_PIXEL_FORMAT_NV12: 99 | case HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL: 100 | case HAL_PIXEL_FORMAT_YCbCr_422_I: 101 | case HAL_PIXEL_FORMAT_YCbCr_422_888: 102 | case HAL_PIXEL_FORMAT_YCbCr_444_888: 103 | case HAL_PIXEL_FORMAT_YCrCb_420_SP: 104 | case HAL_PIXEL_FORMAT_Y16: 105 | case HAL_PIXEL_FORMAT_P010_INTEL: 106 | return true; 107 | default: 108 | return false; 109 | } 110 | 111 | return false; 112 | } 113 | 114 | #endif 115 | -------------------------------------------------------------------------------- /cros_gralloc/i915_private_android.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifdef DRV_I915 8 | 9 | #include 10 | 11 | #include "i915_private.h" 12 | 13 | uint32_t i915_private_convert_format(int format); 14 | 15 | int32_t i915_private_invert_format(int format); 16 | 17 | bool i915_private_supported_yuv_format(uint32_t droid_format); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /cros_gralloc/i915_private_android_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | /* 8 | * Android graphics.h defines the formats and leaves 0x100 - 0x1FF 9 | * range available for HAL implementation specific formats. 10 | */ 11 | 12 | #ifndef i915_PRIVATE_ANDROID_TYPES_H_ 13 | #define i915_PRIVATE_ANDROID_TYPES_H_ 14 | 15 | #ifdef USE_GRALLOC1 16 | #include 17 | #endif 18 | 19 | enum { HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL = 0x100, 20 | HAL_PIXEL_FORMAT_NV12_LINEAR_INTEL = 0x101, 21 | HAL_PIXEL_FORMAT_YCrCb_422_H_INTEL = 0x102, 22 | HAL_PIXEL_FORMAT_NV12_LINEAR_PACKED_INTEL = 0x103, 23 | HAL_PIXEL_FORMAT_YCbCr_422_H_INTEL = 0x104, 24 | HAL_PIXEL_FORMAT_NV12_X_TILED_INTEL = 0x105, 25 | HAL_PIXEL_FORMAT_RGBA_5551_INTEL = 0x106, 26 | HAL_PIXEL_FORMAT_RGBA_4444_INTEL = 0x107, 27 | HAL_PIXEL_FORMAT_GENERIC_8BIT_INTEL = 0x108, 28 | HAL_PIXEL_FORMAT_YCbCr_411_INTEL = 0x109, 29 | HAL_PIXEL_FORMAT_YCbCr_420_H_INTEL = 0x10A, 30 | HAL_PIXEL_FORMAT_YCbCr_422_V_INTEL = 0x10B, 31 | HAL_PIXEL_FORMAT_YCbCr_444_INTEL = 0x10C, 32 | HAL_PIXEL_FORMAT_RGBP_INTEL = 0x10D, 33 | HAL_PIXEL_FORMAT_BGRP_INTEL = 0x10E, 34 | HAL_PIXEL_FORMAT_NV12_LINEAR_CAMERA_INTEL = 0x10F, 35 | HAL_PIXEL_FORMAT_P010_INTEL = 0x110, 36 | HAL_PIXEL_FORMAT_Z16_INTEL = 0x111, 37 | HAL_PIXEL_FORMAT_UVMAP64_INTEL = 0x112, 38 | HAL_PIXEL_FORMAT_A2R10G10B10_INTEL = 0x113, 39 | HAL_PIXEL_FORMAT_A2B10G10R10_INTEL = 0x114, 40 | HAL_PIXEL_FORMAT_YCrCb_NORMAL_INTEL = 0x115, 41 | HAL_PIXEL_FORMAT_YCrCb_SWAPUVY_INTEL = 0x116, 42 | HAL_PIXEL_FORMAT_YCrCb_SWAPUV_INTEL = 0x117, 43 | HAL_PIXEL_FORMAT_YCrCb_SWAPY_INTEL = 0x118, 44 | HAL_PIXEL_FORMAT_X2R10G10B10_INTEL = 0x119, 45 | HAL_PIXEL_FORMAT_X2B10G10R10_INTEL = 0x11A, 46 | HAL_PIXEL_FORMAT_P016_INTEL = 0x11C, 47 | HAL_PIXEL_FORMAT_Y210_INTEL = 0x11D, 48 | HAL_PIXEL_FORMAT_Y216_INTEL = 0x11E, 49 | HAL_PIXEL_FORMAT_Y410_INTEL = 0x11F, 50 | HAL_PIXEL_FORMAT_Y416_INTEL = 0x120, 51 | HAL_PIXEL_FORMAT_Y8I_INTEL = 0x121, 52 | HAL_PIXEL_FORMAT_Y12I_INTEL = 0x122, 53 | HAL_PIXEL_FORMAT_YUYV_INTEL = HAL_PIXEL_FORMAT_YCrCb_NORMAL_INTEL, 54 | HAL_PIXEL_FORMAT_YUY2_INTEL = HAL_PIXEL_FORMAT_YCrCb_NORMAL_INTEL, 55 | HAL_PIXEL_FORMAT_VYUY_INTEL = HAL_PIXEL_FORMAT_YCrCb_SWAPUVY_INTEL, 56 | HAL_PIXEL_FORMAT_YVYU_INTEL = HAL_PIXEL_FORMAT_YCrCb_SWAPUV_INTEL, 57 | HAL_PIXEL_FORMAT_UYVY_INTEL = HAL_PIXEL_FORMAT_YCrCb_SWAPY_INTEL, 58 | HAL_PIXEL_FORMAT_NV12_TILED_INTEL = HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL, 59 | HAL_PIXEL_FORMAT_NV12_INTEL = HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL, 60 | HAL_PIXEL_FORMAT_INTEL_NV12 = HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL, 61 | HAL_PIXEL_FORMAT_NV12 = 0x10F, 62 | HAL_PIXEL_FORMAT_YUV420PackedSemiPlanar_INTEL = 0x7FA00E00, 63 | HAL_PIXEL_FORMAT_YUV420PackedSemiPlanar_Tiled_INTEL = 0x7FA00F00, 64 | }; 65 | 66 | #ifdef USE_GRALLOC1 67 | enum { GRALLOC1_FUNCTION_SET_MODIFIER = 101, 68 | GRALLOC1_FUNCTION_GET_BYTE_STRIDE = 102, 69 | GRALLOC1_FUNCTION_GET_PRIME = 103, 70 | GRALLOC1_FUNCTION_SET_INTERLACE = 104, 71 | GRALLOC1_FUNCTION_SET_PROTECTIONINFO = 105, 72 | GRALLOC1_LAST_CUSTOM = 500 }; 73 | 74 | typedef int32_t /*gralloc1_error_t*/ (*GRALLOC1_PFN_SET_MODIFIER)( 75 | gralloc1_device_t *device, gralloc1_buffer_descriptor_t descriptor, uint64_t modifier); 76 | 77 | typedef int32_t /*gralloc1_error_t*/ (*GRALLOC1_PFN_GET_BYTE_STRIDE)( 78 | gralloc1_device_t *device, buffer_handle_t buffer, uint32_t *outStride, uint32_t size); 79 | 80 | typedef int32_t /*gralloc1_error_t*/ (*GRALLOC1_PFN_GET_PRIME)( 81 | gralloc1_device_t *device, buffer_handle_t buffer, uint32_t *prime); 82 | 83 | typedef int32_t /*gralloc1_error_t*/ (*GRALLOC1_PFN_SET_INTERLACE)( 84 | gralloc1_device_t *device, buffer_handle_t buffer, uint32_t interlace); 85 | 86 | typedef int32_t /*gralloc1_error_t*/ (*GRALLOC1_PFN_SET_PROTECTIONINFO)( 87 | gralloc1_device_t *device, buffer_handle_t buffer, uint32_t protection_info); 88 | 89 | typedef union intel_protection_info_type_t { 90 | uint32_t value; 91 | struct { 92 | uint32_t is_encrypted : 8; 93 | uint32_t pavp_sesion_id : 8; 94 | uint32_t pavp_instance_id: 16; 95 | }; 96 | }intel_protection_info_type_t; 97 | 98 | #endif 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /drv.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "drv_priv.h" 19 | #include "helpers.h" 20 | #include "util.h" 21 | #include "i915_private.h" 22 | 23 | #ifdef DRV_AMDGPU 24 | extern struct backend backend_amdgpu; 25 | #endif 26 | extern struct backend backend_cirrus; 27 | extern struct backend backend_evdi; 28 | #ifdef DRV_EXYNOS 29 | extern struct backend backend_exynos; 30 | #endif 31 | extern struct backend backend_gma500; 32 | #ifdef DRV_I915 33 | extern struct backend backend_i915; 34 | #endif 35 | #ifdef DRV_MARVELL 36 | extern struct backend backend_marvell; 37 | #endif 38 | #ifdef DRV_MEDIATEK 39 | extern struct backend backend_mediatek; 40 | #endif 41 | extern struct backend backend_nouveau; 42 | #ifdef DRV_RADEON 43 | extern struct backend backend_radeon; 44 | #endif 45 | #ifdef DRV_ROCKCHIP 46 | extern struct backend backend_rockchip; 47 | #endif 48 | #ifdef DRV_TEGRA 49 | extern struct backend backend_tegra; 50 | #endif 51 | extern struct backend backend_udl; 52 | #ifdef DRV_VC4 53 | extern struct backend backend_vc4; 54 | #endif 55 | extern struct backend backend_vgem; 56 | extern struct backend backend_virtio_gpu; 57 | 58 | static struct backend *drv_get_backend(int fd) 59 | { 60 | drmVersionPtr drm_version; 61 | unsigned int i; 62 | 63 | drm_version = drmGetVersion(fd); 64 | 65 | if (!drm_version) 66 | return NULL; 67 | 68 | struct backend *backend_list[] = { 69 | #ifdef DRV_AMDGPU 70 | &backend_amdgpu, 71 | #endif 72 | &backend_cirrus, &backend_evdi, 73 | #ifdef DRV_EXYNOS 74 | &backend_exynos, 75 | #endif 76 | &backend_gma500, 77 | #ifdef DRV_I915 78 | &backend_i915, 79 | #endif 80 | #ifdef DRV_MARVELL 81 | &backend_marvell, 82 | #endif 83 | #ifdef DRV_MEDIATEK 84 | &backend_mediatek, 85 | #endif 86 | &backend_nouveau, 87 | #ifdef DRV_RADEON 88 | &backend_radeon, 89 | #endif 90 | #ifdef DRV_ROCKCHIP 91 | &backend_rockchip, 92 | #endif 93 | #ifdef DRV_TEGRA 94 | &backend_tegra, 95 | #endif 96 | &backend_udl, 97 | #ifdef DRV_VC4 98 | &backend_vc4, 99 | #endif 100 | &backend_vgem, &backend_virtio_gpu, 101 | }; 102 | 103 | for (i = 0; i < ARRAY_SIZE(backend_list); i++) 104 | if (!strcmp(drm_version->name, backend_list[i]->name)) { 105 | drmFreeVersion(drm_version); 106 | return backend_list[i]; 107 | } 108 | 109 | drmFreeVersion(drm_version); 110 | return NULL; 111 | } 112 | 113 | struct driver *drv_create(int fd) 114 | { 115 | struct driver *drv; 116 | int ret; 117 | 118 | drv = (struct driver *)calloc(1, sizeof(*drv)); 119 | 120 | if (!drv) 121 | return NULL; 122 | 123 | drv->fd = fd; 124 | drv->backend = drv_get_backend(fd); 125 | 126 | if (!drv->backend) 127 | goto free_driver; 128 | 129 | drv->buffer_table = drmHashCreate(); 130 | if (!drv->buffer_table) 131 | goto free_driver; 132 | 133 | drv->map_table = drmHashCreate(); 134 | if (!drv->map_table) 135 | goto free_buffer_table; 136 | 137 | /* Start with a power of 2 number of allocations. */ 138 | drv->combos.allocations = 2; 139 | drv->combos.size = 0; 140 | 141 | drv->combos.data = calloc(drv->combos.allocations, sizeof(struct combination)); 142 | if (!drv->combos.data) 143 | goto free_map_table; 144 | 145 | if (drv->backend->init) { 146 | ret = drv->backend->init(drv); 147 | if (ret) { 148 | free(drv->combos.data); 149 | goto free_map_table; 150 | } 151 | } 152 | 153 | ATOMIC_VAR_INIT(drv->driver_lock); 154 | 155 | return drv; 156 | 157 | free_map_table: 158 | drmHashDestroy(drv->map_table); 159 | free_buffer_table: 160 | drmHashDestroy(drv->buffer_table); 161 | free_driver: 162 | free(drv); 163 | return NULL; 164 | } 165 | 166 | void drv_destroy(struct driver *drv) 167 | { 168 | ATOMIC_LOCK(&drv->driver_lock); 169 | 170 | close(drv->fd); 171 | 172 | if (drv->backend->close) 173 | drv->backend->close(drv); 174 | 175 | drmHashDestroy(drv->buffer_table); 176 | drmHashDestroy(drv->map_table); 177 | 178 | free(drv->combos.data); 179 | 180 | ATOMIC_UNLOCK(&drv->driver_lock); 181 | 182 | free(drv); 183 | } 184 | 185 | int drv_get_fd(struct driver *drv) 186 | { 187 | return drv->fd; 188 | } 189 | 190 | const char *drv_get_name(struct driver *drv) 191 | { 192 | return drv->backend->name; 193 | } 194 | 195 | struct combination *drv_get_combination(struct driver *drv, uint32_t format, uint64_t use_flags) 196 | { 197 | struct combination *curr, *best; 198 | 199 | if (format == DRM_FORMAT_NONE || use_flags == BO_USE_NONE) 200 | return 0; 201 | 202 | best = NULL; 203 | uint32_t i; 204 | for (i = 0; i < drv->combos.size; i++) { 205 | curr = &drv->combos.data[i]; 206 | if ((format == curr->format) && use_flags == (curr->use_flags & use_flags)) 207 | if (!best || best->metadata.priority < curr->metadata.priority) 208 | best = curr; 209 | } 210 | 211 | return best; 212 | } 213 | 214 | struct bo *drv_bo_new(struct driver *drv, uint32_t width, uint32_t height, uint32_t format, 215 | uint64_t use_flags) 216 | { 217 | 218 | struct bo *bo; 219 | bo = (struct bo *)calloc(1, sizeof(*bo)); 220 | 221 | if (!bo) 222 | return NULL; 223 | 224 | bo->drv = drv; 225 | bo->width = width; 226 | bo->height = height; 227 | bo->format = format; 228 | bo->use_flags = use_flags; 229 | bo->num_planes = drv_num_planes_from_format(format); 230 | 231 | if (!bo->num_planes) { 232 | free(bo); 233 | return NULL; 234 | } 235 | 236 | return bo; 237 | } 238 | 239 | struct bo *drv_bo_create(struct driver *drv, uint32_t width, uint32_t height, uint32_t format, 240 | uint64_t use_flags) 241 | { 242 | int ret; 243 | size_t plane; 244 | struct bo *bo; 245 | 246 | bo = drv_bo_new(drv, width, height, format, use_flags); 247 | 248 | if (!bo) 249 | return NULL; 250 | 251 | ret = drv->backend->bo_create(bo, width, height, format, use_flags); 252 | 253 | if (ret) { 254 | free(bo); 255 | return NULL; 256 | } 257 | 258 | ATOMIC_LOCK(&drv->driver_lock); 259 | 260 | for (plane = 0; plane < bo->num_planes; plane++) { 261 | if (plane > 0) 262 | assert(bo->offsets[plane] >= bo->offsets[plane - 1]); 263 | 264 | drv_increment_reference_count(drv, bo, plane); 265 | } 266 | 267 | ATOMIC_UNLOCK(&drv->driver_lock); 268 | 269 | return bo; 270 | } 271 | 272 | struct bo *drv_bo_create_with_modifiers(struct driver *drv, uint32_t width, uint32_t height, 273 | uint32_t format, const uint64_t *modifiers, uint32_t count) 274 | { 275 | int ret; 276 | size_t plane; 277 | struct bo *bo; 278 | 279 | if (!drv->backend->bo_create_with_modifiers) { 280 | errno = ENOENT; 281 | return NULL; 282 | } 283 | 284 | bo = drv_bo_new(drv, width, height, format, BO_USE_NONE); 285 | 286 | if (!bo) 287 | return NULL; 288 | 289 | ret = drv->backend->bo_create_with_modifiers(bo, width, height, format, modifiers, count); 290 | 291 | if (ret) { 292 | free(bo); 293 | return NULL; 294 | } 295 | 296 | ATOMIC_LOCK(&drv->driver_lock); 297 | 298 | for (plane = 0; plane < bo->num_planes; plane++) { 299 | if (plane > 0) 300 | assert(bo->offsets[plane] >= bo->offsets[plane - 1]); 301 | 302 | drv_increment_reference_count(drv, bo, plane); 303 | } 304 | 305 | ATOMIC_UNLOCK(&drv->driver_lock); 306 | 307 | return bo; 308 | } 309 | 310 | void drv_bo_destroy(struct bo *bo) 311 | { 312 | size_t plane; 313 | uintptr_t total = 0; 314 | struct driver *drv = bo->drv; 315 | 316 | ATOMIC_LOCK(&drv->driver_lock); 317 | 318 | for (plane = 0; plane < bo->num_planes; plane++) 319 | drv_decrement_reference_count(drv, bo, plane); 320 | 321 | for (plane = 0; plane < bo->num_planes; plane++) 322 | total += drv_get_reference_count(drv, bo, plane); 323 | 324 | ATOMIC_UNLOCK(&drv->driver_lock); 325 | 326 | if (total == 0) { 327 | assert(drv_map_info_destroy(bo) == 0); 328 | bo->drv->backend->bo_destroy(bo); 329 | } 330 | 331 | free(bo); 332 | } 333 | 334 | struct bo *drv_bo_import(struct driver *drv, struct drv_import_fd_data *data) 335 | { 336 | int ret; 337 | size_t plane; 338 | struct bo *bo; 339 | off_t seek_end; 340 | 341 | bo = drv_bo_new(drv, data->width, data->height, data->format, data->use_flags); 342 | 343 | if (!bo) 344 | return NULL; 345 | 346 | ret = drv->backend->bo_import(bo, data); 347 | if (ret) { 348 | free(bo); 349 | return NULL; 350 | } 351 | 352 | for (plane = 0; plane < bo->num_planes; plane++) { 353 | bo->strides[plane] = data->strides[plane]; 354 | bo->offsets[plane] = data->offsets[plane]; 355 | bo->format_modifiers[plane] = data->format_modifiers[plane]; 356 | 357 | seek_end = lseek(data->fds[plane], 0, SEEK_END); 358 | if (seek_end == (off_t)(-1)) { 359 | fprintf(stderr, "drv: lseek() failed with %s\n", strerror(errno)); 360 | goto destroy_bo; 361 | } 362 | 363 | lseek(data->fds[plane], 0, SEEK_SET); 364 | if (plane == bo->num_planes - 1 || data->offsets[plane + 1] == 0) 365 | bo->sizes[plane] = seek_end - data->offsets[plane]; 366 | else 367 | bo->sizes[plane] = data->offsets[plane + 1] - data->offsets[plane]; 368 | 369 | if ((int64_t)bo->offsets[plane] + bo->sizes[plane] > seek_end) { 370 | fprintf(stderr, "drv: buffer size is too large.\n"); 371 | goto destroy_bo; 372 | } 373 | 374 | bo->total_size += bo->sizes[plane]; 375 | } 376 | 377 | return bo; 378 | 379 | destroy_bo: 380 | drv_bo_destroy(bo); 381 | return NULL; 382 | } 383 | 384 | void *drv_bo_map(struct bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height, 385 | uint32_t map_flags, struct map_info **map_data, size_t plane) 386 | { 387 | void *ptr; 388 | uint8_t *addr; 389 | size_t offset; 390 | struct map_info *data; 391 | 392 | assert(width > 0); 393 | assert(height > 0); 394 | assert(x + width <= drv_bo_get_width(bo)); 395 | assert(y + height <= drv_bo_get_height(bo)); 396 | assert(BO_MAP_READ_WRITE & map_flags); 397 | /* No CPU access for protected buffers. */ 398 | assert(!(bo->use_flags & BO_USE_PROTECTED)); 399 | 400 | ATOMIC_LOCK(&bo->drv->driver_lock); 401 | 402 | if (!drmHashLookup(bo->drv->map_table, bo->handles[plane].u32, &ptr)) { 403 | data = (struct map_info *)ptr; 404 | /* TODO(gsingh): support mapping same buffer with different flags. */ 405 | assert(data->map_flags == map_flags); 406 | data->refcount++; 407 | goto success; 408 | } 409 | 410 | data = calloc(1, sizeof(*data)); 411 | addr = bo->drv->backend->bo_map(bo, data, plane, map_flags); 412 | if (addr == MAP_FAILED) { 413 | *map_data = NULL; 414 | free(data); 415 | ATOMIC_UNLOCK(&bo->drv->driver_lock); 416 | return MAP_FAILED; 417 | } 418 | 419 | data->refcount = 1; 420 | data->addr = addr; 421 | data->handle = bo->handles[plane].u32; 422 | data->map_flags = map_flags; 423 | drmHashInsert(bo->drv->map_table, bo->handles[plane].u32, (void *)data); 424 | 425 | success: 426 | drv_bo_invalidate(bo, data); 427 | *map_data = data; 428 | offset = drv_bo_get_plane_stride(bo, plane) * y; 429 | offset += drv_stride_from_format(bo->format, x, plane); 430 | addr = (uint8_t *)data->addr; 431 | addr += drv_bo_get_plane_offset(bo, plane) + offset; 432 | ATOMIC_UNLOCK(&bo->drv->driver_lock); 433 | 434 | return (void *)addr; 435 | } 436 | 437 | int drv_bo_unmap(struct bo *bo, struct map_info *data) 438 | { 439 | int ret = drv_bo_flush(bo, data); 440 | if (ret) 441 | return ret; 442 | 443 | ATOMIC_LOCK(&bo->drv->driver_lock); 444 | 445 | if (!--data->refcount) { 446 | ret = bo->drv->backend->bo_unmap(bo, data); 447 | drmHashDelete(bo->drv->map_table, data->handle); 448 | free(data); 449 | } 450 | 451 | ATOMIC_UNLOCK(&bo->drv->driver_lock);; 452 | 453 | return ret; 454 | } 455 | 456 | int drv_bo_invalidate(struct bo *bo, struct map_info *data) 457 | { 458 | int ret = 0; 459 | assert(data); 460 | assert(data->refcount >= 0); 461 | 462 | if (bo->drv->backend->bo_invalidate) 463 | ret = bo->drv->backend->bo_invalidate(bo, data); 464 | 465 | return ret; 466 | } 467 | 468 | int drv_bo_flush(struct bo *bo, struct map_info *data) 469 | { 470 | int ret = 0; 471 | assert(data); 472 | assert(data->refcount >= 0); 473 | assert(!(bo->use_flags & BO_USE_PROTECTED)); 474 | 475 | if (bo->drv->backend->bo_flush) 476 | ret = bo->drv->backend->bo_flush(bo, data); 477 | 478 | return ret; 479 | } 480 | 481 | uint32_t drv_bo_get_width(struct bo *bo) 482 | { 483 | return bo->width; 484 | } 485 | 486 | uint32_t drv_bo_get_height(struct bo *bo) 487 | { 488 | return bo->height; 489 | } 490 | 491 | uint32_t drv_bo_get_stride_or_tiling(struct bo *bo) 492 | { 493 | return bo->tiling ? bo->tiling : drv_bo_get_plane_stride(bo, 0); 494 | } 495 | 496 | size_t drv_bo_get_num_planes(struct bo *bo) 497 | { 498 | return bo->num_planes; 499 | } 500 | 501 | union bo_handle drv_bo_get_plane_handle(struct bo *bo, size_t plane) 502 | { 503 | return bo->handles[plane]; 504 | } 505 | 506 | #ifndef DRM_RDWR 507 | #define DRM_RDWR O_RDWR 508 | #endif 509 | 510 | int drv_bo_get_plane_fd(struct bo *bo, size_t plane) 511 | { 512 | 513 | int ret, fd; 514 | assert(plane < bo->num_planes); 515 | 516 | ret = drmPrimeHandleToFD(bo->drv->fd, bo->handles[plane].u32, DRM_CLOEXEC | DRM_RDWR, &fd); 517 | 518 | return (ret) ? ret : fd; 519 | } 520 | 521 | uint32_t drv_bo_get_plane_offset(struct bo *bo, size_t plane) 522 | { 523 | assert(plane < bo->num_planes); 524 | return bo->offsets[plane]; 525 | } 526 | 527 | uint32_t drv_bo_get_plane_size(struct bo *bo, size_t plane) 528 | { 529 | assert(plane < bo->num_planes); 530 | return bo->sizes[plane]; 531 | } 532 | 533 | uint32_t drv_bo_get_plane_stride(struct bo *bo, size_t plane) 534 | { 535 | assert(plane < bo->num_planes); 536 | return bo->strides[plane]; 537 | } 538 | 539 | uint64_t drv_bo_get_plane_format_modifier(struct bo *bo, size_t plane) 540 | { 541 | assert(plane < bo->num_planes); 542 | return bo->format_modifiers[plane]; 543 | } 544 | 545 | uint32_t drv_bo_get_format(struct bo *bo) 546 | { 547 | return bo->format; 548 | } 549 | 550 | uint32_t drv_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags) 551 | { 552 | if (drv->backend->resolve_format) 553 | return drv->backend->resolve_format(format, use_flags); 554 | 555 | return format; 556 | } 557 | 558 | size_t drv_num_planes_from_format(uint32_t format) 559 | { 560 | switch (format) { 561 | case DRM_FORMAT_ABGR1555: 562 | case DRM_FORMAT_ABGR2101010: 563 | case DRM_FORMAT_ABGR4444: 564 | case DRM_FORMAT_ABGR8888: 565 | case DRM_FORMAT_ARGB1555: 566 | case DRM_FORMAT_ARGB2101010: 567 | case DRM_FORMAT_ARGB4444: 568 | case DRM_FORMAT_ARGB8888: 569 | case DRM_FORMAT_AYUV: 570 | case DRM_FORMAT_BGR233: 571 | case DRM_FORMAT_BGR565: 572 | case DRM_FORMAT_BGR888: 573 | case DRM_FORMAT_BGRA1010102: 574 | case DRM_FORMAT_BGRA4444: 575 | case DRM_FORMAT_BGRA5551: 576 | case DRM_FORMAT_BGRA8888: 577 | case DRM_FORMAT_BGRX1010102: 578 | case DRM_FORMAT_BGRX4444: 579 | case DRM_FORMAT_BGRX5551: 580 | case DRM_FORMAT_BGRX8888: 581 | case DRM_FORMAT_C8: 582 | case DRM_FORMAT_GR88: 583 | case DRM_FORMAT_R8: 584 | case DRM_FORMAT_RG88: 585 | case DRM_FORMAT_RGB332: 586 | case DRM_FORMAT_RGB565: 587 | case DRM_FORMAT_RGB888: 588 | case DRM_FORMAT_RGBA1010102: 589 | case DRM_FORMAT_RGBA4444: 590 | case DRM_FORMAT_RGBA5551: 591 | case DRM_FORMAT_RGBA8888: 592 | case DRM_FORMAT_RGBX1010102: 593 | case DRM_FORMAT_RGBX4444: 594 | case DRM_FORMAT_RGBX5551: 595 | case DRM_FORMAT_RGBX8888: 596 | case DRM_FORMAT_UYVY: 597 | case DRM_FORMAT_VYUY: 598 | case DRM_FORMAT_XBGR1555: 599 | case DRM_FORMAT_XBGR2101010: 600 | case DRM_FORMAT_XBGR4444: 601 | case DRM_FORMAT_XBGR8888: 602 | case DRM_FORMAT_XRGB1555: 603 | case DRM_FORMAT_XRGB2101010: 604 | case DRM_FORMAT_XRGB4444: 605 | case DRM_FORMAT_XRGB8888: 606 | case DRM_FORMAT_YUYV: 607 | case DRM_FORMAT_YVYU: 608 | return 1; 609 | case DRM_FORMAT_NV12: 610 | case DRM_FORMAT_NV21: 611 | return 2; 612 | case DRM_FORMAT_YVU420: 613 | case DRM_FORMAT_YVU420_ANDROID: 614 | return 3; 615 | } 616 | 617 | return i915_private_num_planes_from_format(format); 618 | } 619 | 620 | uint32_t drv_num_buffers_per_bo(struct bo *bo) 621 | { 622 | uint32_t count = 0; 623 | size_t plane, p; 624 | 625 | for (plane = 0; plane < bo->num_planes; plane++) { 626 | for (p = 0; p < plane; p++) 627 | if (bo->handles[p].u32 == bo->handles[plane].u32) 628 | break; 629 | if (p == plane) 630 | count++; 631 | } 632 | 633 | return count; 634 | } 635 | -------------------------------------------------------------------------------- /drv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifndef DRV_H_ 8 | #define DRV_H_ 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #include 15 | #include 16 | 17 | #define DRV_MAX_PLANES 4 18 | 19 | // clang-format off 20 | /* Use flags */ 21 | #define BO_USE_NONE 0 22 | #define BO_USE_SCANOUT (1ull << 0) 23 | #define BO_USE_CURSOR (1ull << 1) 24 | #define BO_USE_CURSOR_64X64 BO_USE_CURSOR 25 | #define BO_USE_RENDERING (1ull << 2) 26 | #define BO_USE_LINEAR (1ull << 3) 27 | #define BO_USE_SW_READ_NEVER (1ull << 4) 28 | #define BO_USE_SW_READ_RARELY (1ull << 5) 29 | #define BO_USE_SW_READ_OFTEN (1ull << 6) 30 | #define BO_USE_SW_WRITE_NEVER (1ull << 7) 31 | #define BO_USE_SW_WRITE_RARELY (1ull << 8) 32 | #define BO_USE_SW_WRITE_OFTEN (1ull << 9) 33 | #define BO_USE_EXTERNAL_DISP (1ull << 10) 34 | #define BO_USE_PROTECTED (1ull << 11) 35 | #define BO_USE_HW_VIDEO_ENCODER (1ull << 12) 36 | #define BO_USE_CAMERA_WRITE (1ull << 13) 37 | #define BO_USE_CAMERA_READ (1ull << 14) 38 | #define BO_USE_RENDERSCRIPT (1ull << 16) 39 | #define BO_USE_TEXTURE (1ull << 17) 40 | 41 | /* Map flags */ 42 | #define BO_MAP_NONE 0 43 | #define BO_MAP_READ (1 << 0) 44 | #define BO_MAP_WRITE (1 << 1) 45 | #define BO_MAP_READ_WRITE (BO_MAP_READ | BO_MAP_WRITE) 46 | 47 | /* This is our extension to . We need to make sure we don't step 48 | * on the namespace of already defined formats, which can be done by using invalid 49 | * fourcc codes. 50 | */ 51 | 52 | #define DRM_FORMAT_NONE fourcc_code('0', '0', '0', '0') 53 | #define DRM_FORMAT_YVU420_ANDROID fourcc_code('9', '9', '9', '7') 54 | #define DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED fourcc_code('9', '9', '9', '8') 55 | #define DRM_FORMAT_FLEX_YCbCr_420_888 fourcc_code('9', '9', '9', '9') 56 | 57 | // clang-format on 58 | struct driver; 59 | struct bo; 60 | struct combination; 61 | 62 | union bo_handle { 63 | void *ptr; 64 | int32_t s32; 65 | uint32_t u32; 66 | int64_t s64; 67 | uint64_t u64; 68 | }; 69 | 70 | struct drv_import_fd_data { 71 | int fds[DRV_MAX_PLANES]; 72 | uint32_t strides[DRV_MAX_PLANES]; 73 | uint32_t offsets[DRV_MAX_PLANES]; 74 | uint64_t format_modifiers[DRV_MAX_PLANES]; 75 | uint32_t width; 76 | uint32_t height; 77 | uint32_t format; 78 | uint64_t use_flags; 79 | }; 80 | 81 | struct map_info { 82 | void *addr; 83 | size_t length; 84 | uint32_t handle; 85 | uint32_t map_flags; 86 | int32_t refcount; 87 | void *priv; 88 | }; 89 | 90 | struct driver *drv_create(int fd); 91 | 92 | void drv_destroy(struct driver *drv); 93 | 94 | int drv_get_fd(struct driver *drv); 95 | 96 | const char *drv_get_name(struct driver *drv); 97 | 98 | struct combination *drv_get_combination(struct driver *drv, uint32_t format, uint64_t use_flags); 99 | 100 | struct bo *drv_bo_new(struct driver *drv, uint32_t width, uint32_t height, uint32_t format, 101 | uint64_t use_flags); 102 | 103 | struct bo *drv_bo_create(struct driver *drv, uint32_t width, uint32_t height, uint32_t format, 104 | uint64_t use_flags); 105 | 106 | struct bo *drv_bo_create_with_modifiers(struct driver *drv, uint32_t width, uint32_t height, 107 | uint32_t format, const uint64_t *modifiers, uint32_t count); 108 | 109 | void drv_bo_destroy(struct bo *bo); 110 | 111 | struct bo *drv_bo_import(struct driver *drv, struct drv_import_fd_data *data); 112 | 113 | void *drv_bo_map(struct bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height, 114 | uint32_t map_flags, struct map_info **map_data, size_t plane); 115 | 116 | int drv_bo_unmap(struct bo *bo, struct map_info *data); 117 | 118 | int drv_bo_invalidate(struct bo *bo, struct map_info *data); 119 | 120 | int drv_bo_flush(struct bo *bo, struct map_info *data); 121 | 122 | uint32_t drv_bo_get_width(struct bo *bo); 123 | 124 | uint32_t drv_bo_get_height(struct bo *bo); 125 | 126 | uint32_t drv_bo_get_stride_or_tiling(struct bo *bo); 127 | 128 | size_t drv_bo_get_num_planes(struct bo *bo); 129 | 130 | union bo_handle drv_bo_get_plane_handle(struct bo *bo, size_t plane); 131 | 132 | int drv_bo_get_plane_fd(struct bo *bo, size_t plane); 133 | 134 | uint32_t drv_bo_get_plane_offset(struct bo *bo, size_t plane); 135 | 136 | uint32_t drv_bo_get_plane_size(struct bo *bo, size_t plane); 137 | 138 | uint32_t drv_bo_get_plane_stride(struct bo *bo, size_t plane); 139 | 140 | uint64_t drv_bo_get_plane_format_modifier(struct bo *bo, size_t plane); 141 | 142 | uint32_t drv_bo_get_format(struct bo *bo); 143 | 144 | uint32_t drv_bo_get_stride_in_pixels(struct bo *bo); 145 | 146 | uint32_t drv_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags); 147 | 148 | size_t drv_num_planes_from_format(uint32_t format); 149 | 150 | uint32_t drv_num_buffers_per_bo(struct bo *bo); 151 | 152 | #ifdef __cplusplus 153 | } 154 | #endif 155 | 156 | #endif 157 | -------------------------------------------------------------------------------- /drv_priv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifndef DRV_PRIV_H 8 | #define DRV_PRIV_H 9 | 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "drv.h" 17 | 18 | #ifndef DISABLE_LOCK 19 | #define ATOMIC_LOCK(X) \ 20 | while (atomic_flag_test_and_set(X)) { \ 21 | } 22 | 23 | #define ATOMIC_UNLOCK(X) \ 24 | atomic_flag_clear(X); 25 | #else 26 | #define ATOMIC_LOCK(X) ((void)0) 27 | #define ATOMIC_UNLOCK(X) ((void)0) 28 | #endif 29 | 30 | struct bo { 31 | struct driver *drv; 32 | uint32_t width; 33 | uint32_t height; 34 | uint32_t format; 35 | uint32_t tiling; 36 | size_t num_planes; 37 | union bo_handle handles[DRV_MAX_PLANES]; 38 | uint32_t offsets[DRV_MAX_PLANES]; 39 | uint32_t sizes[DRV_MAX_PLANES]; 40 | uint32_t strides[DRV_MAX_PLANES]; 41 | uint64_t format_modifiers[DRV_MAX_PLANES]; 42 | uint64_t use_flags; 43 | size_t total_size; 44 | void *priv; 45 | }; 46 | 47 | struct kms_item { 48 | uint32_t format; 49 | uint64_t modifier; 50 | uint64_t use_flags; 51 | }; 52 | 53 | struct format_metadata { 54 | uint32_t priority; 55 | uint32_t tiling; 56 | uint64_t modifier; 57 | }; 58 | 59 | struct combination { 60 | uint32_t format; 61 | struct format_metadata metadata; 62 | uint64_t use_flags; 63 | }; 64 | 65 | struct combinations { 66 | struct combination *data; 67 | uint32_t size; 68 | uint32_t allocations; 69 | }; 70 | 71 | struct driver { 72 | int fd; 73 | struct backend *backend; 74 | void *priv; 75 | void *buffer_table; 76 | void *map_table; 77 | struct combinations combos; 78 | atomic_flag driver_lock; 79 | }; 80 | 81 | struct backend { 82 | char *name; 83 | int (*init)(struct driver *drv); 84 | void (*close)(struct driver *drv); 85 | int (*bo_create)(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, 86 | uint64_t use_flags); 87 | int (*bo_create_with_modifiers)(struct bo *bo, uint32_t width, uint32_t height, 88 | uint32_t format, const uint64_t *modifiers, uint32_t count); 89 | int (*bo_destroy)(struct bo *bo); 90 | int (*bo_import)(struct bo *bo, struct drv_import_fd_data *data); 91 | void *(*bo_map)(struct bo *bo, struct map_info *data, size_t plane, uint32_t map_flags); 92 | int (*bo_unmap)(struct bo *bo, struct map_info *data); 93 | int (*bo_invalidate)(struct bo *bo, struct map_info *data); 94 | int (*bo_flush)(struct bo *bo, struct map_info *data); 95 | uint32_t (*resolve_format)(uint32_t format, uint64_t use_flags); 96 | }; 97 | 98 | // clang-format off 99 | #define BO_USE_RENDER_MASK BO_USE_LINEAR | BO_USE_PROTECTED | BO_USE_RENDERING | \ 100 | BO_USE_RENDERSCRIPT | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN | \ 101 | BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY | BO_USE_TEXTURE 102 | 103 | #define BO_USE_TEXTURE_MASK BO_USE_LINEAR | BO_USE_PROTECTED | BO_USE_RENDERSCRIPT | \ 104 | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN | \ 105 | BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY | BO_USE_TEXTURE 106 | 107 | #define BO_USE_SW_MASK BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN | \ 108 | BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY 109 | 110 | #define LINEAR_METADATA (struct format_metadata) { 0, 1, DRM_FORMAT_MOD_NONE } 111 | // clang-format on 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /evdi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #include "drv_priv.h" 8 | #include "helpers.h" 9 | #include "util.h" 10 | 11 | static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 }; 12 | 13 | static int evdi_init(struct driver *drv) 14 | { 15 | int ret; 16 | ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), 17 | &LINEAR_METADATA, BO_USE_RENDER_MASK); 18 | if (ret) 19 | return ret; 20 | 21 | return drv_modify_linear_combinations(drv); 22 | } 23 | 24 | struct backend backend_evdi = { 25 | .name = "evdi", 26 | .init = evdi_init, 27 | .bo_create = drv_dumb_bo_create, 28 | .bo_destroy = drv_dumb_bo_destroy, 29 | .bo_import = drv_prime_bo_import, 30 | .bo_map = drv_dumb_bo_map, 31 | .bo_unmap = drv_bo_munmap, 32 | }; 33 | -------------------------------------------------------------------------------- /exynos.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifdef DRV_EXYNOS 8 | 9 | // clang-format off 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | // clang-format on 17 | 18 | #include "drv_priv.h" 19 | #include "helpers.h" 20 | #include "util.h" 21 | 22 | static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 }; 23 | 24 | static const uint32_t texture_source_formats[] = { DRM_FORMAT_NV12 }; 25 | 26 | static int exynos_init(struct driver *drv) 27 | { 28 | int ret; 29 | ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), 30 | &LINEAR_METADATA, BO_USE_RENDER_MASK); 31 | if (ret) 32 | return ret; 33 | 34 | ret = drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats), 35 | &LINEAR_METADATA, BO_USE_TEXTURE_MASK); 36 | if (ret) 37 | return ret; 38 | 39 | return drv_modify_linear_combinations(drv); 40 | } 41 | 42 | static int exynos_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, 43 | uint64_t use_flags) 44 | { 45 | size_t plane; 46 | 47 | if (format == DRM_FORMAT_NV12) { 48 | uint32_t chroma_height; 49 | /* V4L2 s5p-mfc requires width to be 16 byte aligned and height 32. */ 50 | width = ALIGN(width, 16); 51 | height = ALIGN(height, 32); 52 | chroma_height = ALIGN(height / 2, 32); 53 | bo->strides[0] = bo->strides[1] = width; 54 | /* MFC v8+ requires 64 byte padding in the end of luma and chroma buffers. */ 55 | bo->sizes[0] = bo->strides[0] * height + 64; 56 | bo->sizes[1] = bo->strides[1] * chroma_height + 64; 57 | bo->offsets[0] = bo->offsets[1] = 0; 58 | bo->total_size = bo->sizes[0] + bo->sizes[1]; 59 | } else if (format == DRM_FORMAT_XRGB8888 || format == DRM_FORMAT_ARGB8888) { 60 | bo->strides[0] = drv_stride_from_format(format, width, 0); 61 | bo->total_size = bo->sizes[0] = height * bo->strides[0]; 62 | bo->offsets[0] = 0; 63 | } else { 64 | fprintf(stderr, "drv: unsupported format %X\n", format); 65 | assert(0); 66 | return -EINVAL; 67 | } 68 | 69 | int ret; 70 | for (plane = 0; plane < bo->num_planes; plane++) { 71 | size_t size = bo->sizes[plane]; 72 | struct drm_exynos_gem_create gem_create; 73 | 74 | memset(&gem_create, 0, sizeof(gem_create)); 75 | gem_create.size = size; 76 | gem_create.flags = EXYNOS_BO_NONCONTIG; 77 | 78 | ret = drmIoctl(bo->drv->fd, DRM_IOCTL_EXYNOS_GEM_CREATE, &gem_create); 79 | if (ret) { 80 | fprintf(stderr, "drv: DRM_IOCTL_EXYNOS_GEM_CREATE failed (size=%zu)\n", 81 | size); 82 | goto cleanup_planes; 83 | } 84 | 85 | bo->handles[plane].u32 = gem_create.handle; 86 | } 87 | 88 | return 0; 89 | 90 | cleanup_planes: 91 | for (; plane != 0; plane--) { 92 | struct drm_gem_close gem_close; 93 | memset(&gem_close, 0, sizeof(gem_close)); 94 | gem_close.handle = bo->handles[plane - 1].u32; 95 | int gem_close_ret = drmIoctl(bo->drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close); 96 | if (gem_close_ret) { 97 | fprintf(stderr, "drv: DRM_IOCTL_GEM_CLOSE failed: %d\n", gem_close_ret); 98 | } 99 | } 100 | 101 | return ret; 102 | } 103 | 104 | /* 105 | * Use dumb mapping with exynos even though a GEM buffer is created. 106 | * libdrm does the same thing in exynos_drm.c 107 | */ 108 | struct backend backend_exynos = { 109 | .name = "exynos", 110 | .init = exynos_init, 111 | .bo_create = exynos_bo_create, 112 | .bo_destroy = drv_gem_bo_destroy, 113 | .bo_import = drv_prime_bo_import, 114 | .bo_map = drv_dumb_bo_map, 115 | .bo_unmap = drv_bo_munmap, 116 | }; 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /gbm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "drv.h" 16 | #include "gbm_helpers.h" 17 | #include "gbm_priv.h" 18 | #include "util.h" 19 | 20 | PUBLIC int gbm_device_get_fd(struct gbm_device *gbm) 21 | { 22 | 23 | return drv_get_fd(gbm->drv); 24 | } 25 | 26 | PUBLIC const char *gbm_device_get_backend_name(struct gbm_device *gbm) 27 | { 28 | return drv_get_name(gbm->drv); 29 | } 30 | 31 | PUBLIC int gbm_device_is_format_supported(struct gbm_device *gbm, uint32_t format, uint32_t usage) 32 | { 33 | uint64_t use_flags; 34 | 35 | if (usage & GBM_BO_USE_CURSOR && usage & GBM_BO_USE_RENDERING) 36 | return 0; 37 | 38 | use_flags = gbm_convert_usage(usage); 39 | 40 | return (drv_get_combination(gbm->drv, format, use_flags) != NULL); 41 | } 42 | 43 | PUBLIC struct gbm_device *gbm_create_device(int fd) 44 | { 45 | struct gbm_device *gbm; 46 | 47 | gbm = (struct gbm_device *)malloc(sizeof(*gbm)); 48 | 49 | if (!gbm) 50 | return NULL; 51 | 52 | gbm->drv = drv_create(fd); 53 | if (!gbm->drv) { 54 | free(gbm); 55 | return NULL; 56 | } 57 | 58 | return gbm; 59 | } 60 | 61 | PUBLIC void gbm_device_destroy(struct gbm_device *gbm) 62 | { 63 | drv_destroy(gbm->drv); 64 | free(gbm); 65 | } 66 | 67 | PUBLIC struct gbm_surface *gbm_surface_create(struct gbm_device *gbm, uint32_t width, 68 | uint32_t height, uint32_t format, uint32_t usage) 69 | { 70 | struct gbm_surface *surface = (struct gbm_surface *)malloc(sizeof(*surface)); 71 | 72 | if (!surface) 73 | return NULL; 74 | 75 | return surface; 76 | } 77 | 78 | PUBLIC void gbm_surface_destroy(struct gbm_surface *surface) 79 | { 80 | free(surface); 81 | } 82 | 83 | PUBLIC struct gbm_bo *gbm_surface_lock_front_buffer(struct gbm_surface *surface) 84 | { 85 | return NULL; 86 | } 87 | 88 | PUBLIC void gbm_surface_release_buffer(struct gbm_surface *surface, struct gbm_bo *bo) 89 | { 90 | } 91 | 92 | static struct gbm_bo *gbm_bo_new(struct gbm_device *gbm, uint32_t format) 93 | { 94 | struct gbm_bo *bo; 95 | 96 | bo = (struct gbm_bo *)calloc(1, sizeof(*bo)); 97 | if (!bo) 98 | return NULL; 99 | 100 | bo->gbm = gbm; 101 | bo->gbm_format = format; 102 | 103 | return bo; 104 | } 105 | 106 | PUBLIC struct gbm_bo *gbm_bo_create(struct gbm_device *gbm, uint32_t width, uint32_t height, 107 | uint32_t format, uint32_t usage) 108 | { 109 | struct gbm_bo *bo; 110 | 111 | if (!gbm_device_is_format_supported(gbm, format, usage)) 112 | return NULL; 113 | 114 | bo = gbm_bo_new(gbm, format); 115 | 116 | if (!bo) 117 | return NULL; 118 | 119 | bo->bo = drv_bo_create(gbm->drv, width, height, format, gbm_convert_usage(usage)); 120 | 121 | if (!bo->bo) { 122 | free(bo); 123 | return NULL; 124 | } 125 | 126 | return bo; 127 | } 128 | 129 | PUBLIC struct gbm_bo *gbm_bo_create_with_modifiers(struct gbm_device *gbm, uint32_t width, 130 | uint32_t height, uint32_t format, 131 | const uint64_t *modifiers, uint32_t count) 132 | { 133 | struct gbm_bo *bo; 134 | 135 | bo = gbm_bo_new(gbm, format); 136 | 137 | if (!bo) 138 | return NULL; 139 | 140 | bo->bo = drv_bo_create_with_modifiers(gbm->drv, width, height, format, modifiers, count); 141 | 142 | if (!bo->bo) { 143 | free(bo); 144 | return NULL; 145 | } 146 | 147 | return bo; 148 | } 149 | 150 | PUBLIC void gbm_bo_destroy(struct gbm_bo *bo) 151 | { 152 | if (bo->destroy_user_data) { 153 | bo->destroy_user_data(bo, bo->user_data); 154 | bo->destroy_user_data = NULL; 155 | bo->user_data = NULL; 156 | } 157 | 158 | drv_bo_destroy(bo->bo); 159 | free(bo); 160 | } 161 | 162 | PUBLIC struct gbm_bo *gbm_bo_import(struct gbm_device *gbm, uint32_t type, void *buffer, 163 | uint32_t usage) 164 | { 165 | struct gbm_bo *bo; 166 | struct drv_import_fd_data drv_data; 167 | struct gbm_import_fd_data *fd_data = buffer; 168 | struct gbm_import_fd_planar_data *fd_planar_data = buffer; 169 | uint32_t gbm_format; 170 | size_t num_planes, i; 171 | 172 | memset(&drv_data, 0, sizeof(drv_data)); 173 | drv_data.use_flags = gbm_convert_usage(usage); 174 | switch (type) { 175 | case GBM_BO_IMPORT_FD: 176 | gbm_format = fd_data->format; 177 | drv_data.width = fd_data->width; 178 | drv_data.height = fd_data->height; 179 | drv_data.format = fd_data->format; 180 | drv_data.fds[0] = fd_data->fd; 181 | drv_data.strides[0] = fd_data->stride; 182 | break; 183 | case GBM_BO_IMPORT_FD_PLANAR: 184 | gbm_format = fd_planar_data->format; 185 | drv_data.width = fd_planar_data->width; 186 | drv_data.height = fd_planar_data->height; 187 | drv_data.format = fd_planar_data->format; 188 | num_planes = drv_num_planes_from_format(drv_data.format); 189 | 190 | assert(num_planes); 191 | 192 | for (i = 0; i < num_planes; i++) { 193 | drv_data.fds[i] = fd_planar_data->fds[i]; 194 | drv_data.offsets[i] = fd_planar_data->offsets[i]; 195 | drv_data.strides[i] = fd_planar_data->strides[i]; 196 | drv_data.format_modifiers[i] = fd_planar_data->format_modifiers[i]; 197 | } 198 | 199 | for (i = num_planes; i < GBM_MAX_PLANES; i++) 200 | drv_data.fds[i] = -1; 201 | 202 | break; 203 | default: 204 | return NULL; 205 | } 206 | 207 | if (!gbm_device_is_format_supported(gbm, gbm_format, usage)) 208 | return NULL; 209 | 210 | bo = gbm_bo_new(gbm, gbm_format); 211 | 212 | if (!bo) 213 | return NULL; 214 | 215 | bo->bo = drv_bo_import(gbm->drv, &drv_data); 216 | 217 | if (!bo->bo) { 218 | free(bo); 219 | return NULL; 220 | } 221 | 222 | return bo; 223 | } 224 | 225 | PUBLIC void *gbm_bo_map(struct gbm_bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height, 226 | uint32_t transfer_flags, uint32_t *stride, void **map_data, size_t plane) 227 | { 228 | uint32_t map_flags; 229 | if (!bo || width == 0 || height == 0 || !stride || !map_data) 230 | return NULL; 231 | 232 | *stride = gbm_bo_get_plane_stride(bo, plane); 233 | map_flags = (transfer_flags & GBM_BO_TRANSFER_READ) ? BO_MAP_READ : BO_MAP_NONE; 234 | map_flags |= (transfer_flags & GBM_BO_TRANSFER_WRITE) ? BO_MAP_WRITE : BO_MAP_NONE; 235 | return drv_bo_map(bo->bo, x, y, width, height, map_flags, (struct map_info **)map_data, 236 | plane); 237 | } 238 | 239 | PUBLIC void gbm_bo_unmap(struct gbm_bo *bo, void *map_data) 240 | { 241 | assert(bo); 242 | drv_bo_unmap(bo->bo, map_data); 243 | } 244 | 245 | PUBLIC uint32_t gbm_bo_get_width(struct gbm_bo *bo) 246 | { 247 | return drv_bo_get_width(bo->bo); 248 | } 249 | 250 | PUBLIC uint32_t gbm_bo_get_height(struct gbm_bo *bo) 251 | { 252 | return drv_bo_get_height(bo->bo); 253 | } 254 | 255 | PUBLIC uint32_t gbm_bo_get_stride(struct gbm_bo *bo) 256 | { 257 | return gbm_bo_get_plane_stride(bo, 0); 258 | } 259 | 260 | PUBLIC uint32_t gbm_bo_get_stride_or_tiling(struct gbm_bo *bo) 261 | { 262 | return drv_bo_get_stride_or_tiling(bo->bo); 263 | } 264 | 265 | PUBLIC uint32_t gbm_bo_get_format(struct gbm_bo *bo) 266 | { 267 | return bo->gbm_format; 268 | } 269 | 270 | PUBLIC uint64_t gbm_bo_get_format_modifier(struct gbm_bo *bo) 271 | { 272 | return gbm_bo_get_plane_format_modifier(bo, 0); 273 | } 274 | 275 | PUBLIC struct gbm_device *gbm_bo_get_device(struct gbm_bo *bo) 276 | { 277 | return bo->gbm; 278 | } 279 | 280 | PUBLIC union gbm_bo_handle gbm_bo_get_handle(struct gbm_bo *bo) 281 | { 282 | return gbm_bo_get_plane_handle(bo, 0); 283 | } 284 | 285 | PUBLIC int gbm_bo_get_fd(struct gbm_bo *bo) 286 | { 287 | return gbm_bo_get_plane_fd(bo, 0); 288 | } 289 | 290 | PUBLIC size_t gbm_bo_get_num_planes(struct gbm_bo *bo) 291 | { 292 | return drv_bo_get_num_planes(bo->bo); 293 | } 294 | 295 | PUBLIC union gbm_bo_handle gbm_bo_get_plane_handle(struct gbm_bo *bo, size_t plane) 296 | { 297 | return (union gbm_bo_handle)drv_bo_get_plane_handle(bo->bo, plane).u64; 298 | } 299 | 300 | PUBLIC int gbm_bo_get_plane_fd(struct gbm_bo *bo, size_t plane) 301 | { 302 | return drv_bo_get_plane_fd(bo->bo, plane); 303 | } 304 | 305 | PUBLIC uint32_t gbm_bo_get_plane_offset(struct gbm_bo *bo, size_t plane) 306 | { 307 | return drv_bo_get_plane_offset(bo->bo, plane); 308 | } 309 | 310 | PUBLIC uint32_t gbm_bo_get_plane_size(struct gbm_bo *bo, size_t plane) 311 | { 312 | return drv_bo_get_plane_size(bo->bo, plane); 313 | } 314 | 315 | PUBLIC uint32_t gbm_bo_get_plane_stride(struct gbm_bo *bo, size_t plane) 316 | { 317 | return drv_bo_get_plane_stride(bo->bo, plane); 318 | } 319 | 320 | PUBLIC uint64_t gbm_bo_get_plane_format_modifier(struct gbm_bo *bo, size_t plane) 321 | { 322 | return drv_bo_get_plane_format_modifier(bo->bo, plane); 323 | } 324 | 325 | PUBLIC void gbm_bo_set_user_data(struct gbm_bo *bo, void *data, 326 | void (*destroy_user_data)(struct gbm_bo *, void *)) 327 | { 328 | bo->user_data = data; 329 | bo->destroy_user_data = destroy_user_data; 330 | } 331 | 332 | PUBLIC void *gbm_bo_get_user_data(struct gbm_bo *bo) 333 | { 334 | return bo->user_data; 335 | } 336 | -------------------------------------------------------------------------------- /gbm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2011 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | * DEALINGS IN THE SOFTWARE. 23 | * 24 | * Authors: 25 | * Benjamin Franzke 26 | */ 27 | 28 | #ifndef _GBM_H_ 29 | #define _GBM_H_ 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | 36 | #define __GBM__ 1 37 | 38 | #include 39 | #include 40 | 41 | /** 42 | * \file gbm.h 43 | * \brief Generic Buffer Manager 44 | */ 45 | 46 | struct gbm_device; 47 | struct gbm_bo; 48 | struct gbm_surface; 49 | 50 | /** 51 | * \mainpage The Generic Buffer Manager 52 | * 53 | * This module provides an abstraction that the caller can use to request a 54 | * buffer from the underlying memory management system for the platform. 55 | * 56 | * This allows the creation of portable code whilst still allowing access to 57 | * the underlying memory manager. 58 | */ 59 | 60 | /** 61 | * Abstraction representing the handle to a buffer allocated by the 62 | * manager 63 | */ 64 | union gbm_bo_handle { 65 | void *ptr; 66 | int32_t s32; 67 | uint32_t u32; 68 | int64_t s64; 69 | uint64_t u64; 70 | }; 71 | 72 | #define GBM_MAX_PLANES 4 73 | 74 | #define __gbm_fourcc_code(a,b,c,d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | \ 75 | ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24)) 76 | 77 | #define GBM_FORMAT_BIG_ENDIAN (1<<31) /* format is big endian instead of little endian */ 78 | 79 | /* color index */ 80 | #define GBM_FORMAT_C8 __gbm_fourcc_code('C', '8', ' ', ' ') /* [7:0] C */ 81 | 82 | /* 8 bpp Red */ 83 | #define GBM_FORMAT_R8 __gbm_fourcc_code('R', '8', ' ', ' ') /* [7:0] R */ 84 | 85 | /* 16 bpp RG */ 86 | #define GBM_FORMAT_RG88 __gbm_fourcc_code('R', 'G', '8', '8') /* [15:0] R:G 8:8 little endian */ 87 | #define GBM_FORMAT_GR88 __gbm_fourcc_code('G', 'R', '8', '8') /* [15:0] G:R 8:8 little endian */ 88 | 89 | /* 8 bpp RGB */ 90 | #define GBM_FORMAT_RGB332 __gbm_fourcc_code('R', 'G', 'B', '8') /* [7:0] R:G:B 3:3:2 */ 91 | #define GBM_FORMAT_BGR233 __gbm_fourcc_code('B', 'G', 'R', '8') /* [7:0] B:G:R 2:3:3 */ 92 | 93 | /* 16 bpp RGB */ 94 | #define GBM_FORMAT_XRGB4444 __gbm_fourcc_code('X', 'R', '1', '2') /* [15:0] x:R:G:B 4:4:4:4 little endian */ 95 | #define GBM_FORMAT_XBGR4444 __gbm_fourcc_code('X', 'B', '1', '2') /* [15:0] x:B:G:R 4:4:4:4 little endian */ 96 | #define GBM_FORMAT_RGBX4444 __gbm_fourcc_code('R', 'X', '1', '2') /* [15:0] R:G:B:x 4:4:4:4 little endian */ 97 | #define GBM_FORMAT_BGRX4444 __gbm_fourcc_code('B', 'X', '1', '2') /* [15:0] B:G:R:x 4:4:4:4 little endian */ 98 | 99 | #define GBM_FORMAT_ARGB4444 __gbm_fourcc_code('A', 'R', '1', '2') /* [15:0] A:R:G:B 4:4:4:4 little endian */ 100 | #define GBM_FORMAT_ABGR4444 __gbm_fourcc_code('A', 'B', '1', '2') /* [15:0] A:B:G:R 4:4:4:4 little endian */ 101 | #define GBM_FORMAT_RGBA4444 __gbm_fourcc_code('R', 'A', '1', '2') /* [15:0] R:G:B:A 4:4:4:4 little endian */ 102 | #define GBM_FORMAT_BGRA4444 __gbm_fourcc_code('B', 'A', '1', '2') /* [15:0] B:G:R:A 4:4:4:4 little endian */ 103 | 104 | #define GBM_FORMAT_XRGB1555 __gbm_fourcc_code('X', 'R', '1', '5') /* [15:0] x:R:G:B 1:5:5:5 little endian */ 105 | #define GBM_FORMAT_XBGR1555 __gbm_fourcc_code('X', 'B', '1', '5') /* [15:0] x:B:G:R 1:5:5:5 little endian */ 106 | #define GBM_FORMAT_RGBX5551 __gbm_fourcc_code('R', 'X', '1', '5') /* [15:0] R:G:B:x 5:5:5:1 little endian */ 107 | #define GBM_FORMAT_BGRX5551 __gbm_fourcc_code('B', 'X', '1', '5') /* [15:0] B:G:R:x 5:5:5:1 little endian */ 108 | 109 | #define GBM_FORMAT_ARGB1555 __gbm_fourcc_code('A', 'R', '1', '5') /* [15:0] A:R:G:B 1:5:5:5 little endian */ 110 | #define GBM_FORMAT_ABGR1555 __gbm_fourcc_code('A', 'B', '1', '5') /* [15:0] A:B:G:R 1:5:5:5 little endian */ 111 | #define GBM_FORMAT_RGBA5551 __gbm_fourcc_code('R', 'A', '1', '5') /* [15:0] R:G:B:A 5:5:5:1 little endian */ 112 | #define GBM_FORMAT_BGRA5551 __gbm_fourcc_code('B', 'A', '1', '5') /* [15:0] B:G:R:A 5:5:5:1 little endian */ 113 | 114 | #define GBM_FORMAT_RGB565 __gbm_fourcc_code('R', 'G', '1', '6') /* [15:0] R:G:B 5:6:5 little endian */ 115 | #define GBM_FORMAT_BGR565 __gbm_fourcc_code('B', 'G', '1', '6') /* [15:0] B:G:R 5:6:5 little endian */ 116 | 117 | /* 24 bpp RGB */ 118 | #define GBM_FORMAT_RGB888 __gbm_fourcc_code('R', 'G', '2', '4') /* [23:0] R:G:B little endian */ 119 | #define GBM_FORMAT_BGR888 __gbm_fourcc_code('B', 'G', '2', '4') /* [23:0] B:G:R little endian */ 120 | 121 | /* 32 bpp RGB */ 122 | #define GBM_FORMAT_XRGB8888 __gbm_fourcc_code('X', 'R', '2', '4') /* [31:0] x:R:G:B 8:8:8:8 little endian */ 123 | #define GBM_FORMAT_XBGR8888 __gbm_fourcc_code('X', 'B', '2', '4') /* [31:0] x:B:G:R 8:8:8:8 little endian */ 124 | #define GBM_FORMAT_RGBX8888 __gbm_fourcc_code('R', 'X', '2', '4') /* [31:0] R:G:B:x 8:8:8:8 little endian */ 125 | #define GBM_FORMAT_BGRX8888 __gbm_fourcc_code('B', 'X', '2', '4') /* [31:0] B:G:R:x 8:8:8:8 little endian */ 126 | 127 | #define GBM_FORMAT_ARGB8888 __gbm_fourcc_code('A', 'R', '2', '4') /* [31:0] A:R:G:B 8:8:8:8 little endian */ 128 | #define GBM_FORMAT_ABGR8888 __gbm_fourcc_code('A', 'B', '2', '4') /* [31:0] A:B:G:R 8:8:8:8 little endian */ 129 | #define GBM_FORMAT_RGBA8888 __gbm_fourcc_code('R', 'A', '2', '4') /* [31:0] R:G:B:A 8:8:8:8 little endian */ 130 | #define GBM_FORMAT_BGRA8888 __gbm_fourcc_code('B', 'A', '2', '4') /* [31:0] B:G:R:A 8:8:8:8 little endian */ 131 | 132 | #define GBM_FORMAT_XRGB2101010 __gbm_fourcc_code('X', 'R', '3', '0') /* [31:0] x:R:G:B 2:10:10:10 little endian */ 133 | #define GBM_FORMAT_XBGR2101010 __gbm_fourcc_code('X', 'B', '3', '0') /* [31:0] x:B:G:R 2:10:10:10 little endian */ 134 | #define GBM_FORMAT_RGBX1010102 __gbm_fourcc_code('R', 'X', '3', '0') /* [31:0] R:G:B:x 10:10:10:2 little endian */ 135 | #define GBM_FORMAT_BGRX1010102 __gbm_fourcc_code('B', 'X', '3', '0') /* [31:0] B:G:R:x 10:10:10:2 little endian */ 136 | 137 | #define GBM_FORMAT_ARGB2101010 __gbm_fourcc_code('A', 'R', '3', '0') /* [31:0] A:R:G:B 2:10:10:10 little endian */ 138 | #define GBM_FORMAT_ABGR2101010 __gbm_fourcc_code('A', 'B', '3', '0') /* [31:0] A:B:G:R 2:10:10:10 little endian */ 139 | #define GBM_FORMAT_RGBA1010102 __gbm_fourcc_code('R', 'A', '3', '0') /* [31:0] R:G:B:A 10:10:10:2 little endian */ 140 | #define GBM_FORMAT_BGRA1010102 __gbm_fourcc_code('B', 'A', '3', '0') /* [31:0] B:G:R:A 10:10:10:2 little endian */ 141 | 142 | /* packed YCbCr */ 143 | #define GBM_FORMAT_YUYV __gbm_fourcc_code('Y', 'U', 'Y', 'V') /* [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian */ 144 | #define GBM_FORMAT_YVYU __gbm_fourcc_code('Y', 'V', 'Y', 'U') /* [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian */ 145 | #define GBM_FORMAT_UYVY __gbm_fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */ 146 | #define GBM_FORMAT_VYUY __gbm_fourcc_code('V', 'Y', 'U', 'Y') /* [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian */ 147 | 148 | #define GBM_FORMAT_AYUV __gbm_fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */ 149 | 150 | /* 151 | * 2 plane YCbCr 152 | * index 0 = Y plane, [7:0] Y 153 | * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian 154 | * or 155 | * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian 156 | */ 157 | #define GBM_FORMAT_NV12 __gbm_fourcc_code('N', 'V', '1', '2') /* 2x2 subsampled Cr:Cb plane */ 158 | #define GBM_FORMAT_NV21 __gbm_fourcc_code('N', 'V', '2', '1') /* 2x2 subsampled Cb:Cr plane */ 159 | #define GBM_FORMAT_NV16 __gbm_fourcc_code('N', 'V', '1', '6') /* 2x1 subsampled Cr:Cb plane */ 160 | #define GBM_FORMAT_NV61 __gbm_fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */ 161 | 162 | /* 163 | * 3 plane YCbCr 164 | * index 0: Y plane, [7:0] Y 165 | * index 1: Cb plane, [7:0] Cb 166 | * index 2: Cr plane, [7:0] Cr 167 | * or 168 | * index 1: Cr plane, [7:0] Cr 169 | * index 2: Cb plane, [7:0] Cb 170 | */ 171 | #define GBM_FORMAT_YUV410 __gbm_fourcc_code('Y', 'U', 'V', '9') /* 4x4 subsampled Cb (1) and Cr (2) planes */ 172 | #define GBM_FORMAT_YVU410 __gbm_fourcc_code('Y', 'V', 'U', '9') /* 4x4 subsampled Cr (1) and Cb (2) planes */ 173 | #define GBM_FORMAT_YUV411 __gbm_fourcc_code('Y', 'U', '1', '1') /* 4x1 subsampled Cb (1) and Cr (2) planes */ 174 | #define GBM_FORMAT_YVU411 __gbm_fourcc_code('Y', 'V', '1', '1') /* 4x1 subsampled Cr (1) and Cb (2) planes */ 175 | #define GBM_FORMAT_YUV420 __gbm_fourcc_code('Y', 'U', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes */ 176 | #define GBM_FORMAT_YVU420 __gbm_fourcc_code('Y', 'V', '1', '2') /* 2x2 subsampled Cr (1) and Cb (2) planes */ 177 | #define GBM_FORMAT_YUV422 __gbm_fourcc_code('Y', 'U', '1', '6') /* 2x1 subsampled Cb (1) and Cr (2) planes */ 178 | #define GBM_FORMAT_YVU422 __gbm_fourcc_code('Y', 'V', '1', '6') /* 2x1 subsampled Cr (1) and Cb (2) planes */ 179 | #define GBM_FORMAT_YUV444 __gbm_fourcc_code('Y', 'U', '2', '4') /* non-subsampled Cb (1) and Cr (2) planes */ 180 | #define GBM_FORMAT_YVU444 __gbm_fourcc_code('Y', 'V', '2', '4') /* non-subsampled Cr (1) and Cb (2) planes */ 181 | 182 | /* 183 | * Format Modifiers: 184 | * 185 | * Format modifiers describe, typically, a re-ordering or modification 186 | * of the data in a plane of an FB. This can be used to express tiled/ 187 | * swizzled formats, or compression, or a combination of the two. 188 | * 189 | * The upper 8 bits of the format modifier are a vendor-id as assigned 190 | * below. The lower 56 bits are assigned as vendor sees fit. 191 | */ 192 | 193 | /* Vendor Ids: */ 194 | #define GBM_FORMAT_MOD_NONE 0 195 | #define GBM_FORMAT_MOD_VENDOR_INTEL 0x01 196 | #define GBM_FORMAT_MOD_VENDOR_AMD 0x02 197 | #define GBM_FORMAT_MOD_VENDOR_NV 0x03 198 | #define GBM_FORMAT_MOD_VENDOR_SAMSUNG 0x04 199 | #define GBM_FORMAT_MOD_VENDOR_QCOM 0x05 200 | /* add more to the end as needed */ 201 | 202 | #define gbm_fourcc_mod_code(vendor, val) \ 203 | ((((__u64)GBM_FORMAT_MOD_VENDOR_## vendor) << 56) | (val & 0x00ffffffffffffffULL)) 204 | 205 | /** 206 | * Flags to indicate the intended use for the buffer - these are passed into 207 | * gbm_bo_create(). The caller must set the union of all the flags that are 208 | * appropriate 209 | * 210 | * \sa Use gbm_device_is_format_supported() to check if the combination of format 211 | * and use flags are supported 212 | */ 213 | enum gbm_bo_flags { 214 | /** 215 | * Buffer is going to be presented to the screen using an API such as KMS 216 | */ 217 | GBM_BO_USE_SCANOUT = (1 << 0), 218 | /** 219 | * Buffer is going to be used as cursor 220 | */ 221 | GBM_BO_USE_CURSOR = (1 << 1), 222 | /** 223 | * Deprecated 224 | */ 225 | GBM_BO_USE_CURSOR_64X64 = GBM_BO_USE_CURSOR, 226 | /** 227 | * Buffer is to be used for rendering - for example it is going to be used 228 | * as the storage for a color buffer 229 | */ 230 | GBM_BO_USE_RENDERING = (1 << 2), 231 | /** 232 | * Deprecated 233 | */ 234 | GBM_BO_USE_WRITE = (1 << 3), 235 | /** 236 | * Buffer is guaranteed to be laid out linearly in memory. That is, the 237 | * buffer is laid out as an array with 'height' blocks, each block with 238 | * length 'stride'. Each stride is in the same order as the rows of the 239 | * buffer. 240 | */ 241 | GBM_BO_USE_LINEAR = (1 << 4), 242 | /** 243 | * The buffer will be used as a texture that will be sampled from. 244 | */ 245 | GBM_BO_USE_TEXTURING = (1 << 5), 246 | /** 247 | * The buffer will be written to by a camera subsystem. 248 | */ 249 | GBM_BO_USE_CAMERA_WRITE = (1 << 6), 250 | /** 251 | * The buffer will be read from by a camera subsystem. 252 | */ 253 | GBM_BO_USE_CAMERA_READ = (1 << 7), 254 | /** 255 | * Buffer inaccessible to unprivileged users. 256 | */ 257 | GBM_BO_USE_PROTECTED = (1 << 8), 258 | }; 259 | 260 | int 261 | gbm_device_get_fd(struct gbm_device *gbm); 262 | 263 | const char * 264 | gbm_device_get_backend_name(struct gbm_device *gbm); 265 | 266 | int 267 | gbm_device_is_format_supported(struct gbm_device *gbm, 268 | uint32_t format, uint32_t usage); 269 | 270 | void 271 | gbm_device_destroy(struct gbm_device *gbm); 272 | 273 | struct gbm_device * 274 | gbm_create_device(int fd); 275 | 276 | struct gbm_bo * 277 | gbm_bo_create(struct gbm_device *gbm, 278 | uint32_t width, uint32_t height, 279 | uint32_t format, uint32_t flags); 280 | 281 | struct gbm_bo * 282 | gbm_bo_create_with_modifiers(struct gbm_device *gbm, 283 | uint32_t width, uint32_t height, 284 | uint32_t format, 285 | const uint64_t *modifiers, uint32_t count); 286 | 287 | #define GBM_BO_IMPORT_WL_BUFFER 0x5501 288 | #define GBM_BO_IMPORT_EGL_IMAGE 0x5502 289 | #define GBM_BO_IMPORT_FD 0x5503 290 | #define GBM_BO_IMPORT_FD_PLANAR 0x5504 291 | 292 | struct gbm_import_fd_data { 293 | int fd; 294 | uint32_t width; 295 | uint32_t height; 296 | uint32_t stride; 297 | uint32_t format; 298 | }; 299 | 300 | struct gbm_import_fd_planar_data { 301 | int fds[GBM_MAX_PLANES]; 302 | uint32_t width; 303 | uint32_t height; 304 | uint32_t format; 305 | uint32_t strides[GBM_MAX_PLANES]; 306 | uint32_t offsets[GBM_MAX_PLANES]; 307 | uint64_t format_modifiers[GBM_MAX_PLANES]; 308 | }; 309 | 310 | struct gbm_bo * 311 | gbm_bo_import(struct gbm_device *gbm, uint32_t type, 312 | void *buffer, uint32_t usage); 313 | 314 | /** 315 | * Flags to indicate the type of mapping for the buffer - these are 316 | * passed into gbm_bo_map(). The caller must set the union of all the 317 | * flags that are appropriate. 318 | * 319 | * These flags are independent of the GBM_BO_USE_* creation flags. However, 320 | * mapping the buffer may require copying to/from a staging buffer. 321 | * 322 | * See also: pipe_transfer_usage 323 | */ 324 | enum gbm_bo_transfer_flags { 325 | /** 326 | * Buffer contents read back (or accessed directly) at transfer 327 | * create time. 328 | */ 329 | GBM_BO_TRANSFER_READ = (1 << 0), 330 | /** 331 | * Buffer contents will be written back at unmap time 332 | * (or modified as a result of being accessed directly). 333 | */ 334 | GBM_BO_TRANSFER_WRITE = (1 << 1), 335 | /** 336 | * Read/modify/write 337 | */ 338 | GBM_BO_TRANSFER_READ_WRITE = (GBM_BO_TRANSFER_READ | GBM_BO_TRANSFER_WRITE), 339 | }; 340 | 341 | void * 342 | gbm_bo_map(struct gbm_bo *bo, 343 | uint32_t x, uint32_t y, uint32_t width, uint32_t height, 344 | uint32_t flags, uint32_t *stride, void **map_data, size_t plane); 345 | 346 | void 347 | gbm_bo_unmap(struct gbm_bo *bo, void *map_data); 348 | 349 | uint32_t 350 | gbm_bo_get_width(struct gbm_bo *bo); 351 | 352 | uint32_t 353 | gbm_bo_get_height(struct gbm_bo *bo); 354 | 355 | uint32_t 356 | gbm_bo_get_stride(struct gbm_bo *bo); 357 | 358 | /* Tegra bringup hack to pass tiling parameters at EGLImage creation. */ 359 | uint32_t 360 | gbm_bo_get_stride_or_tiling(struct gbm_bo *bo); 361 | 362 | uint32_t 363 | gbm_bo_get_format(struct gbm_bo *bo); 364 | 365 | uint64_t 366 | gbm_bo_get_format_modifier(struct gbm_bo *bo); 367 | 368 | struct gbm_device * 369 | gbm_bo_get_device(struct gbm_bo *bo); 370 | 371 | union gbm_bo_handle 372 | gbm_bo_get_handle(struct gbm_bo *bo); 373 | 374 | int 375 | gbm_bo_get_fd(struct gbm_bo *bo); 376 | 377 | size_t 378 | gbm_bo_get_num_planes(struct gbm_bo *bo); 379 | 380 | union gbm_bo_handle 381 | gbm_bo_get_plane_handle(struct gbm_bo *bo, size_t plane); 382 | 383 | int 384 | gbm_bo_get_plane_fd(struct gbm_bo *bo, size_t plane); 385 | 386 | uint32_t 387 | gbm_bo_get_plane_offset(struct gbm_bo *bo, size_t plane); 388 | 389 | uint32_t 390 | gbm_bo_get_plane_size(struct gbm_bo *bo, size_t plane); 391 | 392 | uint32_t 393 | gbm_bo_get_plane_stride(struct gbm_bo *bo, size_t plane); 394 | 395 | uint64_t 396 | gbm_bo_get_plane_format_modifier(struct gbm_bo *bo, size_t plane); 397 | 398 | void 399 | gbm_bo_set_user_data(struct gbm_bo *bo, void *data, 400 | void (*destroy_user_data)(struct gbm_bo *, void *)); 401 | 402 | void * 403 | gbm_bo_get_user_data(struct gbm_bo *bo); 404 | 405 | void 406 | gbm_bo_destroy(struct gbm_bo *bo); 407 | 408 | struct gbm_surface * 409 | gbm_surface_create(struct gbm_device *gbm, 410 | uint32_t width, uint32_t height, 411 | uint32_t format, uint32_t flags); 412 | 413 | struct gbm_bo * 414 | gbm_surface_lock_front_buffer(struct gbm_surface *surface); 415 | 416 | void 417 | gbm_surface_release_buffer(struct gbm_surface *surface, struct gbm_bo *bo); 418 | 419 | int 420 | gbm_surface_has_free_buffers(struct gbm_surface *surface); 421 | 422 | void 423 | gbm_surface_destroy(struct gbm_surface *surface); 424 | 425 | #ifdef __cplusplus 426 | } 427 | #endif 428 | 429 | #endif 430 | -------------------------------------------------------------------------------- /gbm.pc: -------------------------------------------------------------------------------- 1 | prefix=/usr 2 | exec_prefix=${prefix} 3 | includedir=${prefix}/include 4 | libdir=${exec_prefix}/lib 5 | 6 | Name: libgbm 7 | Description: A small gbm implementation 8 | Version: 0 9 | Cflags: -I${includedir} 10 | Libs: -L${libdir} -lgbm 11 | -------------------------------------------------------------------------------- /gbm_helpers.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include "drv.h" 11 | #include "gbm.h" 12 | 13 | uint64_t gbm_convert_usage(uint32_t usage) 14 | { 15 | uint64_t use_flags = BO_USE_NONE; 16 | 17 | if (usage & GBM_BO_USE_SCANOUT) 18 | use_flags |= BO_USE_SCANOUT; 19 | if (usage & GBM_BO_USE_CURSOR) 20 | use_flags |= BO_USE_CURSOR; 21 | if (usage & GBM_BO_USE_CURSOR_64X64) 22 | use_flags |= BO_USE_CURSOR_64X64; 23 | if (usage & GBM_BO_USE_RENDERING) 24 | use_flags |= BO_USE_RENDERING; 25 | if (usage & GBM_BO_USE_TEXTURING) 26 | use_flags |= BO_USE_TEXTURE; 27 | if (usage & GBM_BO_USE_LINEAR) 28 | use_flags |= BO_USE_LINEAR; 29 | if (usage & GBM_BO_USE_CAMERA_WRITE) 30 | use_flags |= BO_USE_CAMERA_WRITE; 31 | if (usage & GBM_BO_USE_CAMERA_READ) 32 | use_flags |= BO_USE_CAMERA_READ; 33 | if (usage & GBM_BO_USE_PROTECTED) 34 | use_flags |= BO_USE_PROTECTED; 35 | 36 | return use_flags; 37 | } 38 | -------------------------------------------------------------------------------- /gbm_helpers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifndef GBM_HELPERS_H 8 | #define GBM_HELPERS_H 9 | 10 | uint64_t gbm_convert_usage(uint32_t usage); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /gbm_priv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifndef GBM_PRIV_H 8 | #define GBM_PRIV_H 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "drv.h" 15 | #include "gbm.h" 16 | 17 | struct gbm_device { 18 | struct driver *drv; 19 | }; 20 | 21 | struct gbm_surface { 22 | }; 23 | 24 | struct gbm_bo { 25 | struct gbm_device *gbm; 26 | struct bo *bo; 27 | uint32_t gbm_format; 28 | void *user_data; 29 | void (*destroy_user_data)(struct gbm_bo *, void *); 30 | }; 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /gma500.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #include "drv_priv.h" 8 | #include "helpers.h" 9 | #include "util.h" 10 | 11 | static const uint32_t render_target_formats[] = { DRM_FORMAT_RGBX8888 }; 12 | 13 | static int gma500_init(struct driver *drv) 14 | { 15 | int ret; 16 | ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), 17 | &LINEAR_METADATA, BO_USE_RENDER_MASK); 18 | if (ret) 19 | return ret; 20 | 21 | return drv_modify_linear_combinations(drv); 22 | } 23 | 24 | struct backend backend_gma500 = { 25 | .name = "gma500", 26 | .init = gma500_init, 27 | .bo_create = drv_dumb_bo_create, 28 | .bo_destroy = drv_dumb_bo_destroy, 29 | .bo_import = drv_prime_bo_import, 30 | .bo_map = drv_dumb_bo_map, 31 | .bo_unmap = drv_bo_munmap, 32 | }; 33 | -------------------------------------------------------------------------------- /helpers.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "drv_priv.h" 18 | #include "helpers.h" 19 | #include "i915_private.h" 20 | #include "util.h" 21 | 22 | static uint32_t subsample_stride(uint32_t stride, uint32_t format, size_t plane) 23 | { 24 | 25 | if (plane != 0) { 26 | switch (format) { 27 | case DRM_FORMAT_YVU420: 28 | case DRM_FORMAT_YVU420_ANDROID: 29 | stride = DIV_ROUND_UP(stride, 2); 30 | break; 31 | } 32 | } 33 | 34 | return stride; 35 | } 36 | 37 | static uint32_t bpp_from_format(uint32_t format, size_t plane) 38 | { 39 | assert(plane < drv_num_planes_from_format(format)); 40 | 41 | switch (format) { 42 | case DRM_FORMAT_BGR233: 43 | case DRM_FORMAT_C8: 44 | case DRM_FORMAT_R8: 45 | case DRM_FORMAT_RGB332: 46 | case DRM_FORMAT_YVU420: 47 | case DRM_FORMAT_YVU420_ANDROID: 48 | return 8; 49 | 50 | case DRM_FORMAT_NV12: 51 | case DRM_FORMAT_NV21: 52 | return (plane == 0) ? 8 : 4; 53 | 54 | case DRM_FORMAT_ABGR1555: 55 | case DRM_FORMAT_ABGR4444: 56 | case DRM_FORMAT_ARGB1555: 57 | case DRM_FORMAT_ARGB4444: 58 | case DRM_FORMAT_BGR565: 59 | case DRM_FORMAT_BGRA4444: 60 | case DRM_FORMAT_BGRA5551: 61 | case DRM_FORMAT_BGRX4444: 62 | case DRM_FORMAT_BGRX5551: 63 | case DRM_FORMAT_GR88: 64 | case DRM_FORMAT_RG88: 65 | case DRM_FORMAT_RGB565: 66 | case DRM_FORMAT_RGBA4444: 67 | case DRM_FORMAT_RGBA5551: 68 | case DRM_FORMAT_RGBX4444: 69 | case DRM_FORMAT_RGBX5551: 70 | case DRM_FORMAT_UYVY: 71 | case DRM_FORMAT_VYUY: 72 | case DRM_FORMAT_XBGR1555: 73 | case DRM_FORMAT_XBGR4444: 74 | case DRM_FORMAT_XRGB1555: 75 | case DRM_FORMAT_XRGB4444: 76 | case DRM_FORMAT_YUYV: 77 | case DRM_FORMAT_YVYU: 78 | return 16; 79 | 80 | case DRM_FORMAT_BGR888: 81 | case DRM_FORMAT_RGB888: 82 | return 24; 83 | 84 | case DRM_FORMAT_ABGR2101010: 85 | case DRM_FORMAT_ABGR8888: 86 | case DRM_FORMAT_ARGB2101010: 87 | case DRM_FORMAT_ARGB8888: 88 | case DRM_FORMAT_AYUV: 89 | case DRM_FORMAT_BGRA1010102: 90 | case DRM_FORMAT_BGRA8888: 91 | case DRM_FORMAT_BGRX1010102: 92 | case DRM_FORMAT_BGRX8888: 93 | case DRM_FORMAT_RGBA1010102: 94 | case DRM_FORMAT_RGBA8888: 95 | case DRM_FORMAT_RGBX1010102: 96 | case DRM_FORMAT_RGBX8888: 97 | case DRM_FORMAT_XBGR2101010: 98 | case DRM_FORMAT_XBGR8888: 99 | case DRM_FORMAT_XRGB2101010: 100 | case DRM_FORMAT_XRGB8888: 101 | return 32; 102 | } 103 | 104 | return i915_private_bpp_from_format(format, plane); 105 | } 106 | 107 | uint32_t drv_bo_get_stride_in_pixels(struct bo *bo) 108 | { 109 | uint32_t bytes_per_pixel = DIV_ROUND_UP(bpp_from_format(bo->format, 0), 8); 110 | return DIV_ROUND_UP(bo->strides[0], bytes_per_pixel); 111 | } 112 | 113 | /* 114 | * This function returns the stride for a given format, width and plane. 115 | */ 116 | uint32_t drv_stride_from_format(uint32_t format, uint32_t width, size_t plane) 117 | { 118 | uint32_t stride = DIV_ROUND_UP(width * bpp_from_format(format, plane), 8); 119 | 120 | /* 121 | * The stride of Android YV12 buffers is required to be aligned to 16 bytes 122 | * (see ). 123 | */ 124 | if (format == DRM_FORMAT_YVU420_ANDROID) 125 | stride = (plane == 0) ? ALIGN(stride, 32) : ALIGN(stride, 16); 126 | 127 | return stride; 128 | } 129 | 130 | uint32_t drv_size_from_format(uint32_t format, uint32_t stride, uint32_t height, size_t plane) 131 | { 132 | assert(plane < drv_num_planes_from_format(format)); 133 | uint32_t vertical_subsampling; 134 | 135 | switch (format) { 136 | case DRM_FORMAT_NV12: 137 | case DRM_FORMAT_YVU420: 138 | case DRM_FORMAT_YVU420_ANDROID: 139 | vertical_subsampling = (plane == 0) ? 1 : 2; 140 | break; 141 | default: 142 | i915_private_vertical_subsampling_from_format(&vertical_subsampling, format, plane); 143 | } 144 | 145 | return stride * DIV_ROUND_UP(height, vertical_subsampling); 146 | } 147 | 148 | /* 149 | * This function fills in the buffer object given the driver aligned stride of 150 | * the first plane, height and a format. This function assumes there is just 151 | * one kernel buffer per buffer object. 152 | */ 153 | int drv_bo_from_format(struct bo *bo, uint32_t stride, uint32_t aligned_height, uint32_t format) 154 | { 155 | 156 | size_t p, num_planes; 157 | uint32_t offset = 0; 158 | 159 | num_planes = drv_num_planes_from_format(format); 160 | assert(num_planes); 161 | 162 | /* 163 | * HAL_PIXEL_FORMAT_YV12 requires that (see ): 164 | * - the aligned height is same as the buffer's height. 165 | * - the chroma stride is 16 bytes aligned, i.e., the luma's strides 166 | * is 32 bytes aligned. 167 | */ 168 | if (format == DRM_FORMAT_YVU420_ANDROID) { 169 | assert(aligned_height == bo->height); 170 | assert(stride == ALIGN(stride, 32)); 171 | } 172 | 173 | for (p = 0; p < num_planes; p++) { 174 | bo->strides[p] = subsample_stride(stride, format, p); 175 | bo->sizes[p] = drv_size_from_format(format, bo->strides[p], aligned_height, p); 176 | bo->offsets[p] = offset; 177 | offset += bo->sizes[p]; 178 | } 179 | 180 | bo->total_size = offset; 181 | return 0; 182 | } 183 | 184 | int drv_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, 185 | uint64_t use_flags) 186 | { 187 | int ret; 188 | size_t plane; 189 | uint32_t aligned_width, aligned_height; 190 | struct drm_mode_create_dumb create_dumb; 191 | 192 | aligned_width = width; 193 | aligned_height = height; 194 | if (format == DRM_FORMAT_YVU420_ANDROID) { 195 | /* 196 | * Align width to 32 pixels, so chroma strides are 16 bytes as 197 | * Android requires. 198 | */ 199 | aligned_width = ALIGN(width, 32); 200 | } 201 | 202 | if (format == DRM_FORMAT_YVU420_ANDROID || format == DRM_FORMAT_YVU420) { 203 | aligned_height = 3 * DIV_ROUND_UP(height, 2); 204 | } 205 | 206 | memset(&create_dumb, 0, sizeof(create_dumb)); 207 | create_dumb.height = aligned_height; 208 | create_dumb.width = aligned_width; 209 | create_dumb.bpp = bpp_from_format(format, 0); 210 | create_dumb.flags = 0; 211 | 212 | ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb); 213 | if (ret) { 214 | fprintf(stderr, "drv: DRM_IOCTL_MODE_CREATE_DUMB failed\n"); 215 | return ret; 216 | } 217 | 218 | drv_bo_from_format(bo, create_dumb.pitch, height, format); 219 | 220 | for (plane = 0; plane < bo->num_planes; plane++) 221 | bo->handles[plane].u32 = create_dumb.handle; 222 | 223 | bo->total_size = create_dumb.size; 224 | return 0; 225 | } 226 | 227 | int drv_dumb_bo_destroy(struct bo *bo) 228 | { 229 | struct drm_mode_destroy_dumb destroy_dumb; 230 | int ret; 231 | 232 | memset(&destroy_dumb, 0, sizeof(destroy_dumb)); 233 | destroy_dumb.handle = bo->handles[0].u32; 234 | 235 | ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb); 236 | if (ret) { 237 | fprintf(stderr, "drv: DRM_IOCTL_MODE_DESTROY_DUMB failed (handle=%x)\n", 238 | bo->handles[0].u32); 239 | return ret; 240 | } 241 | 242 | return 0; 243 | } 244 | 245 | int drv_gem_bo_destroy(struct bo *bo) 246 | { 247 | struct drm_gem_close gem_close; 248 | int ret, error = 0; 249 | size_t plane, i; 250 | 251 | for (plane = 0; plane < bo->num_planes; plane++) { 252 | for (i = 0; i < plane; i++) 253 | if (bo->handles[i].u32 == bo->handles[plane].u32) 254 | break; 255 | /* Make sure close hasn't already been called on this handle */ 256 | if (i != plane) 257 | continue; 258 | 259 | memset(&gem_close, 0, sizeof(gem_close)); 260 | gem_close.handle = bo->handles[plane].u32; 261 | 262 | ret = drmIoctl(bo->drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close); 263 | if (ret) { 264 | fprintf(stderr, "drv: DRM_IOCTL_GEM_CLOSE failed (handle=%x) error %d\n", 265 | bo->handles[plane].u32, ret); 266 | error = ret; 267 | } 268 | } 269 | 270 | return error; 271 | } 272 | 273 | int drv_prime_bo_import(struct bo *bo, struct drv_import_fd_data *data) 274 | { 275 | int ret; 276 | size_t plane; 277 | struct drm_prime_handle prime_handle; 278 | 279 | for (plane = 0; plane < bo->num_planes; plane++) { 280 | memset(&prime_handle, 0, sizeof(prime_handle)); 281 | prime_handle.fd = data->fds[plane]; 282 | 283 | ret = drmIoctl(bo->drv->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &prime_handle); 284 | 285 | if (ret) { 286 | fprintf(stderr, "drv: DRM_IOCTL_PRIME_FD_TO_HANDLE failed (fd=%u)\n", 287 | prime_handle.fd); 288 | 289 | /* 290 | * Need to call GEM close on planes that were opened, 291 | * if any. Adjust the num_planes variable to be the 292 | * plane that failed, so GEM close will be called on 293 | * planes before that plane. 294 | */ 295 | bo->num_planes = plane; 296 | drv_gem_bo_destroy(bo); 297 | return ret; 298 | } 299 | 300 | bo->handles[plane].u32 = prime_handle.handle; 301 | } 302 | 303 | ATOMIC_LOCK(&bo->drv->driver_lock); 304 | for (plane = 0; plane < bo->num_planes; plane++) { 305 | drv_increment_reference_count(bo->drv, bo, plane); 306 | } 307 | ATOMIC_UNLOCK(&bo->drv->driver_lock); 308 | 309 | return 0; 310 | } 311 | 312 | void *drv_dumb_bo_map(struct bo *bo, struct map_info *data, size_t plane, uint32_t map_flags) 313 | { 314 | int ret; 315 | size_t i; 316 | struct drm_mode_map_dumb map_dumb; 317 | 318 | memset(&map_dumb, 0, sizeof(map_dumb)); 319 | map_dumb.handle = bo->handles[plane].u32; 320 | 321 | ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb); 322 | if (ret) { 323 | fprintf(stderr, "drv: DRM_IOCTL_MODE_MAP_DUMB failed \n"); 324 | return MAP_FAILED; 325 | } 326 | 327 | for (i = 0; i < bo->num_planes; i++) 328 | if (bo->handles[i].u32 == bo->handles[plane].u32) 329 | data->length += bo->sizes[i]; 330 | 331 | return mmap(0, data->length, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd, 332 | map_dumb.offset); 333 | } 334 | 335 | int drv_bo_munmap(struct bo *bo, struct map_info *data) 336 | { 337 | return munmap(data->addr, data->length); 338 | } 339 | 340 | int drv_map_info_destroy(struct bo *bo) 341 | { 342 | int ret; 343 | void *ptr; 344 | size_t plane; 345 | struct map_info *data; 346 | 347 | /* 348 | * This function is called right before the buffer is destroyed. It will free any mappings 349 | * associated with the buffer. 350 | */ 351 | 352 | for (plane = 0; plane < bo->num_planes; plane++) { 353 | if (!drmHashLookup(bo->drv->map_table, bo->handles[plane].u32, &ptr)) { 354 | data = (struct map_info *)ptr; 355 | ret = bo->drv->backend->bo_unmap(bo, data); 356 | if (ret) { 357 | fprintf(stderr, "drv: munmap failed"); 358 | return ret; 359 | } 360 | 361 | drmHashDelete(bo->drv->map_table, data->handle); 362 | free(data); 363 | } 364 | } 365 | 366 | return 0; 367 | } 368 | 369 | int drv_get_prot(uint32_t map_flags) 370 | { 371 | return (BO_MAP_WRITE & map_flags) ? PROT_WRITE | PROT_READ : PROT_READ; 372 | } 373 | 374 | uintptr_t drv_get_reference_count(struct driver *drv, struct bo *bo, size_t plane) 375 | { 376 | void *count; 377 | uintptr_t num = 0; 378 | 379 | if (!drmHashLookup(drv->buffer_table, bo->handles[plane].u32, &count)) 380 | num = (uintptr_t)(count); 381 | 382 | return num; 383 | } 384 | 385 | void drv_increment_reference_count(struct driver *drv, struct bo *bo, size_t plane) 386 | { 387 | uintptr_t num = drv_get_reference_count(drv, bo, plane); 388 | 389 | /* If a value isn't in the table, drmHashDelete is a no-op */ 390 | drmHashDelete(drv->buffer_table, bo->handles[plane].u32); 391 | drmHashInsert(drv->buffer_table, bo->handles[plane].u32, (void *)(num + 1)); 392 | } 393 | 394 | void drv_decrement_reference_count(struct driver *drv, struct bo *bo, size_t plane) 395 | { 396 | uintptr_t num = drv_get_reference_count(drv, bo, plane); 397 | 398 | drmHashDelete(drv->buffer_table, bo->handles[plane].u32); 399 | 400 | if (num > 0) 401 | drmHashInsert(drv->buffer_table, bo->handles[plane].u32, (void *)(num - 1)); 402 | } 403 | 404 | uint32_t drv_log_base2(uint32_t value) 405 | { 406 | int ret = 0; 407 | 408 | while (value >>= 1) 409 | ++ret; 410 | 411 | return ret; 412 | } 413 | 414 | int drv_add_combination(struct driver *drv, uint32_t format, struct format_metadata *metadata, 415 | uint64_t use_flags) 416 | { 417 | struct combinations *combos = &drv->combos; 418 | if (combos->size >= combos->allocations) { 419 | struct combination *new_data; 420 | combos->allocations *= 2; 421 | new_data = realloc(combos->data, combos->allocations * sizeof(*combos->data)); 422 | if (!new_data) 423 | return -ENOMEM; 424 | 425 | combos->data = new_data; 426 | } 427 | 428 | combos->data[combos->size].format = format; 429 | combos->data[combos->size].metadata.priority = metadata->priority; 430 | combos->data[combos->size].metadata.tiling = metadata->tiling; 431 | combos->data[combos->size].metadata.modifier = metadata->modifier; 432 | combos->data[combos->size].use_flags = use_flags; 433 | combos->size++; 434 | return 0; 435 | } 436 | 437 | int drv_add_combinations(struct driver *drv, const uint32_t *formats, uint32_t num_formats, 438 | struct format_metadata *metadata, uint64_t use_flags) 439 | { 440 | int ret; 441 | uint32_t i; 442 | for (i = 0; i < num_formats; i++) { 443 | ret = drv_add_combination(drv, formats[i], metadata, use_flags); 444 | if (ret) 445 | return ret; 446 | } 447 | 448 | return 0; 449 | } 450 | 451 | void drv_modify_combination(struct driver *drv, uint32_t format, struct format_metadata *metadata, 452 | uint64_t use_flags) 453 | { 454 | uint32_t i; 455 | struct combination *combo; 456 | /* Attempts to add the specified flags to an existing combination. */ 457 | for (i = 0; i < drv->combos.size; i++) { 458 | combo = &drv->combos.data[i]; 459 | if (combo->format == format && combo->metadata.tiling == metadata->tiling && 460 | combo->metadata.modifier == metadata->modifier) 461 | combo->use_flags |= use_flags; 462 | } 463 | } 464 | 465 | struct kms_item *drv_query_kms(struct driver *drv, uint32_t *num_items) 466 | { 467 | struct kms_item *items; 468 | uint64_t plane_type, use_flag; 469 | uint32_t i, j, k, allocations, item_size; 470 | 471 | drmModePlanePtr plane; 472 | drmModePropertyPtr prop; 473 | drmModePlaneResPtr resources; 474 | drmModeObjectPropertiesPtr props; 475 | 476 | /* Start with a power of 2 number of allocations. */ 477 | allocations = 2; 478 | item_size = 0; 479 | items = calloc(allocations, sizeof(*items)); 480 | if (!items) 481 | goto out; 482 | 483 | /* 484 | * The ability to return universal planes is only complete on 485 | * ChromeOS kernel versions >= v3.18. The SET_CLIENT_CAP ioctl 486 | * therefore might return an error code, so don't check it. If it 487 | * fails, it'll just return the plane list as overlay planes, which is 488 | * fine in our case (our drivers already have cursor bits set). 489 | * modetest in libdrm does the same thing. 490 | */ 491 | drmSetClientCap(drv->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); 492 | 493 | resources = drmModeGetPlaneResources(drv->fd); 494 | if (!resources) 495 | goto out; 496 | 497 | for (i = 0; i < resources->count_planes; i++) { 498 | plane = drmModeGetPlane(drv->fd, resources->planes[i]); 499 | if (!plane) 500 | goto out; 501 | 502 | props = drmModeObjectGetProperties(drv->fd, plane->plane_id, DRM_MODE_OBJECT_PLANE); 503 | if (!props) 504 | goto out; 505 | 506 | for (j = 0; j < props->count_props; j++) { 507 | prop = drmModeGetProperty(drv->fd, props->props[j]); 508 | if (prop) { 509 | if (strcmp(prop->name, "type") == 0) { 510 | plane_type = props->prop_values[j]; 511 | } 512 | 513 | drmModeFreeProperty(prop); 514 | } 515 | } 516 | 517 | switch (plane_type) { 518 | case DRM_PLANE_TYPE_OVERLAY: 519 | case DRM_PLANE_TYPE_PRIMARY: 520 | use_flag = BO_USE_SCANOUT; 521 | break; 522 | case DRM_PLANE_TYPE_CURSOR: 523 | use_flag = BO_USE_CURSOR; 524 | break; 525 | default: 526 | assert(0); 527 | } 528 | 529 | for (j = 0; j < plane->count_formats; j++) { 530 | bool found = false; 531 | for (k = 0; k < item_size; k++) { 532 | if (items[k].format == plane->formats[j] && 533 | items[k].modifier == DRM_FORMAT_MOD_INVALID) { 534 | items[k].use_flags |= use_flag; 535 | found = true; 536 | break; 537 | } 538 | } 539 | 540 | if (!found && item_size >= allocations) { 541 | struct kms_item *new_data = NULL; 542 | allocations *= 2; 543 | new_data = realloc(items, allocations * sizeof(*items)); 544 | if (!new_data) { 545 | item_size = 0; 546 | goto out; 547 | } 548 | 549 | items = new_data; 550 | } 551 | 552 | if (!found) { 553 | items[item_size].format = plane->formats[j]; 554 | items[item_size].modifier = DRM_FORMAT_MOD_INVALID; 555 | items[item_size].use_flags = use_flag; 556 | item_size++; 557 | } 558 | } 559 | 560 | drmModeFreeObjectProperties(props); 561 | drmModeFreePlane(plane); 562 | } 563 | 564 | drmModeFreePlaneResources(resources); 565 | out: 566 | if (items && item_size == 0) { 567 | free(items); 568 | items = NULL; 569 | } 570 | 571 | *num_items = item_size; 572 | return items; 573 | } 574 | 575 | int drv_modify_linear_combinations(struct driver *drv) 576 | { 577 | uint32_t i, j, num_items; 578 | struct kms_item *items; 579 | struct combination *combo; 580 | 581 | /* 582 | * All current drivers can scanout linear XRGB8888/ARGB8888 as a primary 583 | * plane and as a cursor. Some drivers don't support 584 | * drmModeGetPlaneResources, so add the combination here. Note that the 585 | * kernel disregards the alpha component of ARGB unless it's an overlay 586 | * plane. 587 | */ 588 | drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &LINEAR_METADATA, 589 | BO_USE_CURSOR | BO_USE_SCANOUT); 590 | drv_modify_combination(drv, DRM_FORMAT_ARGB8888, &LINEAR_METADATA, 591 | BO_USE_CURSOR | BO_USE_SCANOUT); 592 | 593 | items = drv_query_kms(drv, &num_items); 594 | if (!items || !num_items) 595 | return 0; 596 | 597 | for (i = 0; i < num_items; i++) { 598 | for (j = 0; j < drv->combos.size; j++) { 599 | combo = &drv->combos.data[j]; 600 | if (items[i].format == combo->format) 601 | combo->use_flags |= BO_USE_SCANOUT; 602 | } 603 | } 604 | 605 | free(items); 606 | return 0; 607 | } 608 | 609 | /* 610 | * Pick the best modifier from modifiers, according to the ordering 611 | * given by modifier_order. 612 | */ 613 | uint64_t drv_pick_modifier(const uint64_t *modifiers, uint32_t count, 614 | const uint64_t *modifier_order, uint32_t order_count) 615 | { 616 | uint32_t i, j; 617 | 618 | for (i = 0; i < order_count; i++) { 619 | for (j = 0; j < count; j++) { 620 | if (modifiers[j] == modifier_order[i]) { 621 | return modifiers[j]; 622 | } 623 | } 624 | } 625 | 626 | return DRM_FORMAT_MOD_LINEAR; 627 | } 628 | -------------------------------------------------------------------------------- /helpers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifndef HELPERS_H 8 | #define HELPERS_H 9 | 10 | #include "drv.h" 11 | 12 | uint32_t drv_stride_from_format(uint32_t format, uint32_t width, size_t plane); 13 | uint32_t drv_size_from_format(uint32_t format, uint32_t stride, uint32_t height, size_t plane); 14 | int drv_bo_from_format(struct bo *bo, uint32_t stride, uint32_t aligned_height, uint32_t format); 15 | int drv_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, 16 | uint64_t use_flags); 17 | int drv_dumb_bo_destroy(struct bo *bo); 18 | int drv_gem_bo_destroy(struct bo *bo); 19 | int drv_prime_bo_import(struct bo *bo, struct drv_import_fd_data *data); 20 | void *drv_dumb_bo_map(struct bo *bo, struct map_info *data, size_t plane, uint32_t map_flags); 21 | int drv_bo_munmap(struct bo *bo, struct map_info *data); 22 | int drv_map_info_destroy(struct bo *bo); 23 | int drv_get_prot(uint32_t map_flags); 24 | uintptr_t drv_get_reference_count(struct driver *drv, struct bo *bo, size_t plane); 25 | void drv_increment_reference_count(struct driver *drv, struct bo *bo, size_t plane); 26 | void drv_decrement_reference_count(struct driver *drv, struct bo *bo, size_t plane); 27 | uint32_t drv_log_base2(uint32_t value); 28 | int drv_add_combination(struct driver *drv, uint32_t format, struct format_metadata *metadata, 29 | uint64_t usage); 30 | int drv_add_combinations(struct driver *drv, const uint32_t *formats, uint32_t num_formats, 31 | struct format_metadata *metadata, uint64_t usage); 32 | void drv_modify_combination(struct driver *drv, uint32_t format, struct format_metadata *metadata, 33 | uint64_t usage); 34 | struct kms_item *drv_query_kms(struct driver *drv, uint32_t *num_items); 35 | int drv_modify_linear_combinations(struct driver *drv); 36 | uint64_t drv_pick_modifier(const uint64_t *modifiers, uint32_t count, 37 | const uint64_t *modifier_order, uint32_t order_count); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /i915_private.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifdef DRV_I915 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "drv_priv.h" 19 | #include "helpers.h" 20 | #include "util.h" 21 | #include "i915_private.h" 22 | 23 | static const uint32_t private_linear_source_formats[] = { DRM_FORMAT_R16, DRM_FORMAT_NV16, 24 | DRM_FORMAT_YUV420, DRM_FORMAT_YUV422, 25 | DRM_FORMAT_YUV444, DRM_FORMAT_NV21, 26 | DRM_FORMAT_P010 }; 27 | 28 | static const uint32_t private_rgb24_formats[] = { DRM_FORMAT_RGB888, DRM_FORMAT_BGR888 }; 29 | 30 | static const uint32_t private_source_formats[] = { DRM_FORMAT_P010, DRM_FORMAT_NV12_Y_TILED_INTEL }; 31 | 32 | #if !defined(DRM_CAP_CURSOR_WIDTH) 33 | #define DRM_CAP_CURSOR_WIDTH 0x8 34 | #endif 35 | 36 | #if !defined(DRM_CAP_CURSOR_HEIGHT) 37 | #define DRM_CAP_CURSOR_HEIGHT 0x9 38 | #endif 39 | 40 | static const uint32_t kDefaultCursorWidth = 64; 41 | static const uint32_t kDefaultCursorHeight = 64; 42 | 43 | #define BO_USE_CAMERA_MASK BO_USE_CAMERA_READ | BO_USE_SCANOUT | BO_USE_CAMERA_WRITE 44 | 45 | static void get_preferred_cursor_attributes(uint32_t drm_fd, uint64_t *cursor_width, 46 | uint64_t *cursor_height) 47 | { 48 | uint64_t width = 0, height = 0; 49 | if (drmGetCap(drm_fd, DRM_CAP_CURSOR_WIDTH, &width)) { 50 | fprintf(stderr, "cannot get cursor width. \n"); 51 | } else if (drmGetCap(drm_fd, DRM_CAP_CURSOR_HEIGHT, &height)) { 52 | fprintf(stderr, "cannot get cursor height. \n"); 53 | } 54 | 55 | if (!width) 56 | width = kDefaultCursorWidth; 57 | 58 | *cursor_width = width; 59 | 60 | if (!height) 61 | height = kDefaultCursorHeight; 62 | 63 | *cursor_height = height; 64 | } 65 | 66 | int i915_private_init(struct driver *drv, uint64_t *cursor_width, uint64_t *cursor_height) 67 | { 68 | get_preferred_cursor_attributes(drv->fd, cursor_width, cursor_height); 69 | return 0; 70 | } 71 | 72 | int i915_private_add_combinations(struct driver *drv) 73 | { 74 | struct format_metadata metadata; 75 | uint64_t render_flags, texture_flags; 76 | 77 | render_flags = BO_USE_RENDER_MASK; 78 | texture_flags = BO_USE_TEXTURE_MASK; 79 | 80 | metadata.tiling = I915_TILING_NONE; 81 | metadata.priority = 1; 82 | metadata.modifier = DRM_FORMAT_MOD_NONE; 83 | 84 | drv_modify_combination(drv, DRM_FORMAT_ABGR8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT); 85 | drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata, 86 | BO_USE_TEXTURE | BO_USE_CAMERA_MASK); 87 | drv_modify_combination(drv, DRM_FORMAT_YUYV, &metadata, 88 | BO_USE_TEXTURE | BO_USE_CAMERA_MASK | BO_USE_RENDERING); 89 | drv_modify_combination(drv, DRM_FORMAT_VYUY, &metadata, 90 | BO_USE_TEXTURE | BO_USE_CAMERA_MASK | BO_USE_RENDERING); 91 | drv_modify_combination(drv, DRM_FORMAT_UYVY, &metadata, 92 | BO_USE_TEXTURE | BO_USE_CAMERA_MASK | BO_USE_RENDERING); 93 | drv_modify_combination(drv, DRM_FORMAT_YVYU, &metadata, 94 | BO_USE_TEXTURE | BO_USE_CAMERA_MASK | BO_USE_RENDERING); 95 | drv_modify_combination(drv, DRM_FORMAT_YVU420_ANDROID, &metadata, 96 | BO_USE_TEXTURE | BO_USE_CAMERA_MASK); 97 | drv_modify_combination(drv, DRM_FORMAT_RGB565, &metadata, BO_USE_CAMERA_MASK); 98 | 99 | /* Media/Camera expect these formats support. */ 100 | metadata.tiling = I915_TILING_NONE; 101 | metadata.priority = 1; 102 | metadata.modifier = DRM_FORMAT_MOD_NONE; 103 | drv_add_combinations(drv, private_linear_source_formats, 104 | ARRAY_SIZE(private_linear_source_formats), &metadata, 105 | texture_flags | BO_USE_CAMERA_MASK); 106 | 107 | metadata.tiling = I915_TILING_NONE; 108 | metadata.priority = 1; 109 | metadata.modifier = DRM_FORMAT_MOD_NONE; 110 | drv_add_combination(drv, DRM_FORMAT_ABGR2101010, &metadata, 111 | BO_USE_SCANOUT | BO_USE_TEXTURE | 112 | BO_USE_RENDERING | BO_USE_SW_MASK); 113 | drv_add_combination(drv, DRM_FORMAT_ABGR16161616F, &metadata, 114 | BO_USE_SCANOUT | BO_USE_TEXTURE | BO_USE_RENDERING); 115 | 116 | metadata.tiling = I915_TILING_Y; 117 | metadata.priority = 3; 118 | metadata.modifier = I915_FORMAT_MOD_Y_TILED; 119 | drv_add_combinations(drv, private_source_formats, ARRAY_SIZE(private_source_formats), 120 | &metadata, texture_flags | BO_USE_CAMERA_MASK); 121 | 122 | /* Android CTS tests require this. */ 123 | drv_add_combinations(drv, private_rgb24_formats, ARRAY_SIZE(private_rgb24_formats), 124 | &metadata, BO_USE_SW_MASK); 125 | 126 | texture_flags &= ~BO_USE_RENDERSCRIPT; 127 | texture_flags &= ~BO_USE_SW_WRITE_OFTEN; 128 | texture_flags &= ~BO_USE_SW_READ_OFTEN; 129 | texture_flags &= ~BO_USE_LINEAR; 130 | 131 | metadata.tiling = I915_TILING_X; 132 | metadata.priority = 2; 133 | metadata.modifier = I915_FORMAT_MOD_X_TILED; 134 | 135 | int ret = drv_add_combinations(drv, private_linear_source_formats, 136 | ARRAY_SIZE(private_linear_source_formats), &metadata, 137 | texture_flags | BO_USE_CAMERA_MASK); 138 | if (ret) 139 | return ret; 140 | 141 | return 0; 142 | } 143 | 144 | void i915_private_align_dimensions(uint32_t format, uint32_t *vertical_alignment) 145 | { 146 | switch (format) { 147 | case DRM_FORMAT_NV12_Y_TILED_INTEL: 148 | *vertical_alignment = 64; 149 | break; 150 | } 151 | } 152 | 153 | uint32_t i915_private_bpp_from_format(uint32_t format, size_t plane) 154 | { 155 | assert(plane < drv_num_planes_from_format(format)); 156 | 157 | switch (format) { 158 | case DRM_FORMAT_NV12_Y_TILED_INTEL: 159 | return (plane == 0) ? 8 : 4; 160 | case DRM_FORMAT_P010: 161 | return (plane == 0) ? 16 : 8; 162 | case DRM_FORMAT_YUV420: 163 | case DRM_FORMAT_YUV422: 164 | case DRM_FORMAT_YUV444: 165 | case DRM_FORMAT_NV16: 166 | return 8; 167 | case DRM_FORMAT_R16: 168 | return 16; 169 | case DRM_FORMAT_ABGR2101010: 170 | return 32; 171 | case DRM_FORMAT_ABGR16161616F: 172 | return 64; 173 | } 174 | 175 | fprintf(stderr, "drv: UNKNOWN FORMAT %d\n", format); 176 | return 0; 177 | } 178 | 179 | void i915_private_vertical_subsampling_from_format(uint32_t *vertical_subsampling, uint32_t format, 180 | size_t plane) 181 | { 182 | switch (format) { 183 | case DRM_FORMAT_NV12_Y_TILED_INTEL: 184 | case DRM_FORMAT_YUV420: 185 | case DRM_FORMAT_P010: 186 | *vertical_subsampling = (plane == 0) ? 1 : 2; 187 | break; 188 | default: 189 | *vertical_subsampling = 1; 190 | } 191 | } 192 | 193 | size_t i915_private_num_planes_from_format(uint32_t format) 194 | { 195 | switch (format) { 196 | case DRM_FORMAT_R16: 197 | case DRM_FORMAT_ABGR2101010: 198 | case DRM_FORMAT_ABGR16161616F: 199 | return 1; 200 | case DRM_FORMAT_NV12_Y_TILED_INTEL: 201 | case DRM_FORMAT_NV16: 202 | case DRM_FORMAT_P010: 203 | return 2; 204 | case DRM_FORMAT_YUV420: 205 | case DRM_FORMAT_YUV422: 206 | case DRM_FORMAT_YUV444: 207 | return 3; 208 | } 209 | 210 | fprintf(stderr, "drv: UNKNOWN FORMAT %d\n", format); 211 | return 0; 212 | } 213 | 214 | uint32_t i915_private_resolve_format(uint32_t format, uint64_t usage, uint32_t *resolved_format) 215 | { 216 | switch (format) { 217 | case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED: 218 | /* KBL camera subsystem requires NV12. */ 219 | if (usage & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE)) { 220 | *resolved_format = DRM_FORMAT_NV12; 221 | return 1; 222 | } 223 | 224 | if (usage & BO_USE_TEXTURE) { 225 | *resolved_format = DRM_FORMAT_ABGR8888; 226 | return 1; 227 | } 228 | } 229 | 230 | return 0; 231 | } 232 | 233 | #endif 234 | -------------------------------------------------------------------------------- /i915_private.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifdef DRV_I915 8 | 9 | #include 10 | 11 | #include "i915_private_types.h" 12 | 13 | struct driver; 14 | 15 | /* 16 | * 2 plane YCbCr MSB aligned 17 | * index 0 = Y plane, [15:0] Y:x [10:6] little endian 18 | * index 1 = Cr:Cb plane, [31:0] Cr:x:Cb:x [10:6:10:6] little endian 19 | */ 20 | #define DRM_FORMAT_P010 fourcc_code('P', '0', '1', '0') /* 2x2 subsampled Cr:Cb plane 10 bits per channel */ 21 | 22 | /* 23 | * 2 plane YCbCr MSB aligned 24 | * index 0 = Y plane, [15:0] Y:x [12:4] little endian 25 | * index 1 = Cr:Cb plane, [31:0] Cr:x:Cb:x [12:4:12:4] little endian 26 | */ 27 | #define DRM_FORMAT_P012 fourcc_code('P', '0', '1', '2') /* 2x2 subsampled Cr:Cb plane 12 bits per channel */ 28 | 29 | /* 30 | * 2 plane YCbCr MSB aligned 31 | * index 0 = Y plane, [15:0] Y little endian 32 | * index 1 = Cr:Cb plane, [31:0] Cr:Cb [16:16] little endian 33 | */ 34 | #define DRM_FORMAT_P016 fourcc_code('P', '0', '1', '6') /* 2x2 subsampled Cr:Cb plane 16 bits per channel */ 35 | 36 | /* 64 bpp RGB */ 37 | #define DRM_FORMAT_XRGB161616 fourcc_code('X', 'R', '4', '8') /* [63:0] x:R:G:B 16:16:16:16 little endian */ 38 | #define DRM_FORMAT_XBGR161616 fourcc_code('X', 'B', '4', '8') /* [63:0] x:B:G:R 16:16:16:16 little endian */ 39 | #define DRM_FORMAT_ABGR16161616F fourcc_code('A', 'B', '4', 'H') /* [63:0] x:B:G:R 16:16:16:16 little endian */ 40 | 41 | int i915_private_init(struct driver *drv, uint64_t *cursor_width, uint64_t *cursor_height); 42 | 43 | int i915_private_add_combinations(struct driver *drv); 44 | 45 | void i915_private_align_dimensions(uint32_t format, uint32_t *vertical_alignment); 46 | 47 | uint32_t i915_private_bpp_from_format(uint32_t format, size_t plane); 48 | 49 | void i915_private_vertical_subsampling_from_format(uint32_t *vertical_subsampling, uint32_t format, 50 | size_t plane); 51 | 52 | size_t i915_private_num_planes_from_format(uint32_t format); 53 | 54 | uint32_t i915_private_resolve_format(uint32_t format, uint64_t usage, uint32_t *resolved_format); 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /i915_private_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifdef DRV_I915 8 | 9 | #define DRM_FORMAT_NV12_Y_TILED_INTEL fourcc_code('9', '9', '9', '6') 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /marvell.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifdef DRV_MARVELL 8 | 9 | #include "drv_priv.h" 10 | #include "helpers.h" 11 | #include "util.h" 12 | 13 | static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 }; 14 | 15 | static int marvell_init(struct driver *drv) 16 | { 17 | int ret; 18 | ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), 19 | &LINEAR_METADATA, BO_USE_RENDER_MASK); 20 | if (ret) 21 | return ret; 22 | 23 | return drv_add_linear_combinations(drv, render_target_formats, 24 | ARRAY_SIZE(render_target_formats)); 25 | } 26 | 27 | struct backend backend_marvell = { 28 | .name = "marvell", 29 | .init = marvell_init, 30 | .bo_create = drv_dumb_bo_create, 31 | .bo_destroy = drv_dumb_bo_destroy, 32 | .bo_import = drv_prime_bo_import, 33 | .bo_map = drv_dumb_bo_map, 34 | .bo_unmap = drv_bo_munmap, 35 | }; 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /mediatek.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifdef DRV_MEDIATEK 8 | 9 | // clang-format off 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | // clang-format on 16 | 17 | #include "drv_priv.h" 18 | #include "helpers.h" 19 | #include "util.h" 20 | 21 | struct mediatek_private_map_data { 22 | void *cached_addr; 23 | void *gem_addr; 24 | }; 25 | 26 | static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888, 27 | DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888, 28 | DRM_FORMAT_XRGB8888 }; 29 | 30 | static const uint32_t texture_source_formats[] = { DRM_FORMAT_R8, DRM_FORMAT_YVU420, 31 | DRM_FORMAT_YVU420_ANDROID }; 32 | 33 | static int mediatek_init(struct driver *drv) 34 | { 35 | int ret; 36 | ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), 37 | &LINEAR_METADATA, BO_USE_RENDER_MASK); 38 | if (ret) 39 | return ret; 40 | 41 | ret = drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats), 42 | &LINEAR_METADATA, BO_USE_TEXTURE_MASK); 43 | if (ret) 44 | return ret; 45 | 46 | return drv_modify_linear_combinations(drv); 47 | } 48 | 49 | static int mediatek_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, 50 | uint64_t use_flags) 51 | { 52 | int ret; 53 | size_t plane; 54 | uint32_t stride; 55 | struct drm_mtk_gem_create gem_create; 56 | 57 | /* 58 | * Since the ARM L1 cache line size is 64 bytes, align to that as a 59 | * performance optimization. 60 | */ 61 | stride = drv_stride_from_format(format, width, 0); 62 | stride = ALIGN(stride, 64); 63 | drv_bo_from_format(bo, stride, height, format); 64 | 65 | memset(&gem_create, 0, sizeof(gem_create)); 66 | gem_create.size = bo->total_size; 67 | 68 | ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MTK_GEM_CREATE, &gem_create); 69 | if (ret) { 70 | fprintf(stderr, "drv: DRM_IOCTL_MTK_GEM_CREATE failed (size=%llu)\n", 71 | gem_create.size); 72 | return ret; 73 | } 74 | 75 | for (plane = 0; plane < bo->num_planes; plane++) 76 | bo->handles[plane].u32 = gem_create.handle; 77 | 78 | return 0; 79 | } 80 | 81 | static void *mediatek_bo_map(struct bo *bo, struct map_info *data, size_t plane, uint32_t map_flags) 82 | { 83 | int ret; 84 | struct drm_mtk_gem_map_off gem_map; 85 | struct mediatek_private_map_data *priv; 86 | 87 | memset(&gem_map, 0, sizeof(gem_map)); 88 | gem_map.handle = bo->handles[0].u32; 89 | 90 | ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MTK_GEM_MAP_OFFSET, &gem_map); 91 | if (ret) { 92 | fprintf(stderr, "drv: DRM_IOCTL_MTK_GEM_MAP_OFFSET failed\n"); 93 | return MAP_FAILED; 94 | } 95 | 96 | void *addr = mmap(0, bo->total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd, 97 | gem_map.offset); 98 | 99 | data->length = bo->total_size; 100 | 101 | if (bo->use_flags & BO_USE_RENDERSCRIPT) { 102 | priv = calloc(1, sizeof(*priv)); 103 | priv->cached_addr = calloc(1, bo->total_size); 104 | priv->gem_addr = addr; 105 | memcpy(priv->cached_addr, priv->gem_addr, bo->total_size); 106 | data->priv = priv; 107 | addr = priv->cached_addr; 108 | } 109 | 110 | return addr; 111 | } 112 | 113 | static int mediatek_bo_unmap(struct bo *bo, struct map_info *data) 114 | { 115 | if (data->priv) { 116 | struct mediatek_private_map_data *priv = data->priv; 117 | data->addr = priv->gem_addr; 118 | free(priv->cached_addr); 119 | free(priv); 120 | data->priv = NULL; 121 | } 122 | 123 | return munmap(data->addr, data->length); 124 | } 125 | 126 | static int mediatek_bo_flush(struct bo *bo, struct map_info *data) 127 | { 128 | struct mediatek_private_map_data *priv = data->priv; 129 | if (priv && (data->map_flags & BO_MAP_WRITE)) 130 | memcpy(priv->gem_addr, priv->cached_addr, bo->total_size); 131 | 132 | return 0; 133 | } 134 | 135 | static uint32_t mediatek_resolve_format(uint32_t format, uint64_t use_flags) 136 | { 137 | switch (format) { 138 | case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED: 139 | /*HACK: See b/28671744 */ 140 | return DRM_FORMAT_XBGR8888; 141 | case DRM_FORMAT_FLEX_YCbCr_420_888: 142 | return DRM_FORMAT_YVU420; 143 | default: 144 | return format; 145 | } 146 | } 147 | 148 | struct backend backend_mediatek = { 149 | .name = "mediatek", 150 | .init = mediatek_init, 151 | .bo_create = mediatek_bo_create, 152 | .bo_destroy = drv_gem_bo_destroy, 153 | .bo_import = drv_prime_bo_import, 154 | .bo_map = mediatek_bo_map, 155 | .bo_unmap = mediatek_bo_unmap, 156 | .bo_flush = mediatek_bo_flush, 157 | .resolve_format = mediatek_resolve_format, 158 | }; 159 | 160 | #endif 161 | -------------------------------------------------------------------------------- /nouveau.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #include "drv_priv.h" 8 | #include "helpers.h" 9 | #include "util.h" 10 | 11 | static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 }; 12 | 13 | static int nouveau_init(struct driver *drv) 14 | { 15 | int ret; 16 | ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), 17 | &LINEAR_METADATA, BO_USE_RENDER_MASK); 18 | if (ret) 19 | return ret; 20 | 21 | return drv_modify_linear_combinations(drv); 22 | } 23 | 24 | struct backend backend_nouveau = { 25 | .name = "nouveau", 26 | .init = nouveau_init, 27 | .bo_create = drv_dumb_bo_create, 28 | .bo_destroy = drv_dumb_bo_destroy, 29 | .bo_import = drv_prime_bo_import, 30 | .bo_map = drv_dumb_bo_map, 31 | .bo_unmap = drv_bo_munmap, 32 | }; 33 | -------------------------------------------------------------------------------- /presubmit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright 2017 The Chromium OS Authors. All rights reserved. 3 | # Use of this source code is governed by a BSD-style license that can be 4 | # found in the LICENSE file. 5 | find \ 6 | '(' -name '*.[ch]' -or -name '*.cc' ')' \ 7 | -not -name 'gbm.h' \ 8 | -exec clang-format -style=file -i {} + 9 | -------------------------------------------------------------------------------- /radeon.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #include "drv_priv.h" 8 | #include "helpers.h" 9 | #include "util.h" 10 | 11 | static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 }; 12 | 13 | static int radeon_init(struct driver *drv) 14 | { 15 | int ret; 16 | ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), 17 | &LINEAR_METADATA, BO_USE_RENDER_MASK); 18 | if (ret) 19 | return ret; 20 | 21 | return drv_modify_linear_combinations(drv); 22 | } 23 | 24 | struct backend backend_radeon = { 25 | .name = "radeon", 26 | .init = radeon_init, 27 | .bo_create = drv_dumb_bo_create, 28 | .bo_destroy = drv_dumb_bo_destroy, 29 | .bo_import = drv_prime_bo_import, 30 | .bo_map = drv_dumb_bo_map, 31 | .bo_unmap = drv_bo_munmap, 32 | }; 33 | -------------------------------------------------------------------------------- /rockchip.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifdef DRV_ROCKCHIP 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "drv_priv.h" 18 | #include "helpers.h" 19 | #include "util.h" 20 | 21 | struct rockchip_private_map_data { 22 | void *cached_addr; 23 | void *gem_addr; 24 | }; 25 | 26 | static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888, 27 | DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888, 28 | DRM_FORMAT_XRGB8888 }; 29 | 30 | static const uint32_t texture_source_formats[] = { DRM_FORMAT_R8, DRM_FORMAT_NV12, 31 | DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID }; 32 | 33 | static int afbc_bo_from_format(struct bo *bo, uint32_t width, uint32_t height, uint32_t format) 34 | { 35 | /* We've restricted ourselves to four bytes per pixel. */ 36 | const uint32_t pixel_size = 4; 37 | 38 | const uint32_t clump_width = 4; 39 | const uint32_t clump_height = 4; 40 | 41 | #define AFBC_NARROW 1 42 | #if AFBC_NARROW == 1 43 | const uint32_t block_width = 4 * clump_width; 44 | const uint32_t block_height = 4 * clump_height; 45 | #else 46 | const uint32_t block_width = 8 * clump_width; 47 | const uint32_t block_height = 2 * clump_height; 48 | #endif 49 | 50 | const uint32_t header_block_size = 16; 51 | const uint32_t body_block_size = block_width * block_height * pixel_size; 52 | const uint32_t width_in_blocks = DIV_ROUND_UP(width, block_width); 53 | const uint32_t height_in_blocks = DIV_ROUND_UP(height, block_height); 54 | const uint32_t total_blocks = width_in_blocks * height_in_blocks; 55 | 56 | const uint32_t header_plane_size = total_blocks * header_block_size; 57 | const uint32_t body_plane_size = total_blocks * body_block_size; 58 | 59 | /* GPU requires 64 bytes, but EGL import code expects 1024 byte 60 | * alignement for the body plane. */ 61 | const uint32_t body_plane_alignment = 1024; 62 | 63 | const uint32_t body_plane_offset = ALIGN(header_plane_size, body_plane_alignment); 64 | const uint32_t total_size = body_plane_offset + body_plane_size; 65 | 66 | bo->strides[0] = width_in_blocks * block_width * pixel_size; 67 | bo->sizes[0] = total_size; 68 | bo->offsets[0] = 0; 69 | 70 | bo->total_size = total_size; 71 | 72 | bo->format_modifiers[0] = DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC; 73 | 74 | return 0; 75 | } 76 | 77 | static int rockchip_add_kms_item(struct driver *drv, const struct kms_item *item) 78 | { 79 | int ret; 80 | uint32_t i, j; 81 | uint64_t use_flags; 82 | struct combination *combo; 83 | struct format_metadata metadata; 84 | 85 | for (i = 0; i < drv->combos.size; i++) { 86 | combo = &drv->combos.data[i]; 87 | if (combo->format == item->format) { 88 | if (item->modifier == DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC) { 89 | use_flags = BO_USE_RENDERING | BO_USE_SCANOUT | BO_USE_TEXTURE; 90 | metadata.modifier = item->modifier; 91 | metadata.tiling = 0; 92 | metadata.priority = 2; 93 | 94 | for (j = 0; j < ARRAY_SIZE(texture_source_formats); j++) { 95 | if (item->format == texture_source_formats[j]) 96 | use_flags &= ~BO_USE_RENDERING; 97 | } 98 | 99 | ret = 100 | drv_add_combination(drv, item[i].format, &metadata, use_flags); 101 | if (ret) 102 | return ret; 103 | } else { 104 | combo->use_flags |= item->use_flags; 105 | } 106 | } 107 | } 108 | 109 | return 0; 110 | } 111 | 112 | static int rockchip_init(struct driver *drv) 113 | { 114 | int ret; 115 | uint32_t i, num_items; 116 | struct kms_item *items; 117 | struct format_metadata metadata; 118 | 119 | metadata.tiling = 0; 120 | metadata.priority = 1; 121 | metadata.modifier = DRM_FORMAT_MOD_LINEAR; 122 | 123 | ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), 124 | &metadata, BO_USE_RENDER_MASK); 125 | if (ret) 126 | return ret; 127 | 128 | ret = drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats), 129 | &metadata, BO_USE_TEXTURE_MASK); 130 | if (ret) 131 | return ret; 132 | 133 | drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT); 134 | drv_modify_combination(drv, DRM_FORMAT_ARGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT); 135 | 136 | /* Camera ISP supports only NV12 output. */ 137 | drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata, 138 | BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE); 139 | /* 140 | * R8 format is used for Android's HAL_PIXEL_FORMAT_BLOB and is used for JPEG snapshots 141 | * from camera. 142 | */ 143 | drv_modify_combination(drv, DRM_FORMAT_R8, &metadata, 144 | BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE); 145 | 146 | items = drv_query_kms(drv, &num_items); 147 | if (!items || !num_items) 148 | return 0; 149 | 150 | for (i = 0; i < num_items; i++) { 151 | ret = rockchip_add_kms_item(drv, &items[i]); 152 | if (ret) { 153 | free(items); 154 | return ret; 155 | } 156 | } 157 | 158 | free(items); 159 | return 0; 160 | } 161 | 162 | static bool has_modifier(const uint64_t *list, uint32_t count, uint64_t modifier) 163 | { 164 | uint32_t i; 165 | for (i = 0; i < count; i++) 166 | if (list[i] == modifier) 167 | return true; 168 | 169 | return false; 170 | } 171 | 172 | static int rockchip_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint32_t height, 173 | uint32_t format, const uint64_t *modifiers, 174 | uint32_t count) 175 | { 176 | int ret; 177 | size_t plane; 178 | struct drm_rockchip_gem_create gem_create; 179 | 180 | if (format == DRM_FORMAT_NV12) { 181 | uint32_t w_mbs = DIV_ROUND_UP(ALIGN(width, 16), 16); 182 | uint32_t h_mbs = DIV_ROUND_UP(ALIGN(height, 16), 16); 183 | 184 | uint32_t aligned_width = w_mbs * 16; 185 | uint32_t aligned_height = DIV_ROUND_UP(h_mbs * 16 * 3, 2); 186 | 187 | drv_bo_from_format(bo, aligned_width, height, format); 188 | bo->total_size = bo->strides[0] * aligned_height + w_mbs * h_mbs * 128; 189 | } else if (width <= 2560 && 190 | has_modifier(modifiers, count, DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC)) { 191 | /* If the caller has decided they can use AFBC, always 192 | * pick that */ 193 | afbc_bo_from_format(bo, width, height, format); 194 | } else { 195 | if (!has_modifier(modifiers, count, DRM_FORMAT_MOD_LINEAR)) { 196 | errno = EINVAL; 197 | fprintf(stderr, "no usable modifier found\n"); 198 | return -1; 199 | } 200 | 201 | uint32_t stride; 202 | /* 203 | * Since the ARM L1 cache line size is 64 bytes, align to that 204 | * as a performance optimization. For YV12, the Mali cmem allocator 205 | * requires that chroma planes are aligned to 64-bytes, so align the 206 | * luma plane to 128 bytes. 207 | */ 208 | stride = drv_stride_from_format(format, width, 0); 209 | if (format == DRM_FORMAT_YVU420 || format == DRM_FORMAT_YVU420_ANDROID) 210 | stride = ALIGN(stride, 128); 211 | else 212 | stride = ALIGN(stride, 64); 213 | 214 | drv_bo_from_format(bo, stride, height, format); 215 | } 216 | 217 | memset(&gem_create, 0, sizeof(gem_create)); 218 | gem_create.size = bo->total_size; 219 | 220 | ret = drmIoctl(bo->drv->fd, DRM_IOCTL_ROCKCHIP_GEM_CREATE, &gem_create); 221 | 222 | if (ret) { 223 | fprintf(stderr, "drv: DRM_IOCTL_ROCKCHIP_GEM_CREATE failed (size=%llu)\n", 224 | gem_create.size); 225 | return ret; 226 | } 227 | 228 | for (plane = 0; plane < bo->num_planes; plane++) 229 | bo->handles[plane].u32 = gem_create.handle; 230 | 231 | return 0; 232 | } 233 | 234 | static int rockchip_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, 235 | uint64_t use_flags) 236 | { 237 | uint64_t modifiers[] = { DRM_FORMAT_MOD_LINEAR }; 238 | return rockchip_bo_create_with_modifiers(bo, width, height, format, modifiers, 239 | ARRAY_SIZE(modifiers)); 240 | } 241 | 242 | static void *rockchip_bo_map(struct bo *bo, struct map_info *data, size_t plane, uint32_t map_flags) 243 | { 244 | int ret; 245 | struct drm_rockchip_gem_map_off gem_map; 246 | struct rockchip_private_map_data *priv; 247 | 248 | /* We can only map buffers created with SW access flags, which should 249 | * have no modifiers (ie, not AFBC). */ 250 | if (bo->format_modifiers[0] == DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC) 251 | return MAP_FAILED; 252 | 253 | memset(&gem_map, 0, sizeof(gem_map)); 254 | gem_map.handle = bo->handles[0].u32; 255 | 256 | ret = drmIoctl(bo->drv->fd, DRM_IOCTL_ROCKCHIP_GEM_MAP_OFFSET, &gem_map); 257 | if (ret) { 258 | fprintf(stderr, "drv: DRM_IOCTL_ROCKCHIP_GEM_MAP_OFFSET failed\n"); 259 | return MAP_FAILED; 260 | } 261 | 262 | void *addr = mmap(0, bo->total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd, 263 | gem_map.offset); 264 | 265 | data->length = bo->total_size; 266 | 267 | if (bo->use_flags & BO_USE_RENDERSCRIPT) { 268 | priv = calloc(1, sizeof(*priv)); 269 | priv->cached_addr = calloc(1, bo->total_size); 270 | priv->gem_addr = addr; 271 | memcpy(priv->cached_addr, priv->gem_addr, bo->total_size); 272 | data->priv = priv; 273 | addr = priv->cached_addr; 274 | } 275 | 276 | return addr; 277 | } 278 | 279 | static int rockchip_bo_unmap(struct bo *bo, struct map_info *data) 280 | { 281 | if (data->priv) { 282 | struct rockchip_private_map_data *priv = data->priv; 283 | data->addr = priv->gem_addr; 284 | free(priv->cached_addr); 285 | free(priv); 286 | data->priv = NULL; 287 | } 288 | 289 | return munmap(data->addr, data->length); 290 | } 291 | 292 | static int rockchip_bo_flush(struct bo *bo, struct map_info *data) 293 | { 294 | struct rockchip_private_map_data *priv = data->priv; 295 | if (priv && (data->map_flags & BO_MAP_WRITE)) 296 | memcpy(priv->gem_addr, priv->cached_addr, bo->total_size); 297 | 298 | return 0; 299 | } 300 | 301 | static uint32_t rockchip_resolve_format(uint32_t format, uint64_t use_flags) 302 | { 303 | switch (format) { 304 | case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED: 305 | /* Camera subsystem requires NV12. */ 306 | if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE)) 307 | return DRM_FORMAT_NV12; 308 | /*HACK: See b/28671744 */ 309 | return DRM_FORMAT_XBGR8888; 310 | case DRM_FORMAT_FLEX_YCbCr_420_888: 311 | return DRM_FORMAT_NV12; 312 | default: 313 | return format; 314 | } 315 | } 316 | 317 | struct backend backend_rockchip = { 318 | .name = "rockchip", 319 | .init = rockchip_init, 320 | .bo_create = rockchip_bo_create, 321 | .bo_create_with_modifiers = rockchip_bo_create_with_modifiers, 322 | .bo_destroy = drv_gem_bo_destroy, 323 | .bo_import = drv_prime_bo_import, 324 | .bo_map = rockchip_bo_map, 325 | .bo_unmap = rockchip_bo_unmap, 326 | .bo_flush = rockchip_bo_flush, 327 | .resolve_format = rockchip_resolve_format, 328 | }; 329 | 330 | #endif 331 | -------------------------------------------------------------------------------- /tegra.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifdef DRV_TEGRA 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "drv_priv.h" 17 | #include "helpers.h" 18 | #include "util.h" 19 | 20 | /* 21 | * GOB (Group Of Bytes) is the basic unit of the blocklinear layout. 22 | * GOBs are arranged to blocks, where the height of the block (measured 23 | * in GOBs) is configurable. 24 | */ 25 | #define NV_BLOCKLINEAR_GOB_HEIGHT 8 26 | #define NV_BLOCKLINEAR_GOB_WIDTH 64 27 | #define NV_DEFAULT_BLOCK_HEIGHT_LOG2 4 28 | #define NV_PREFERRED_PAGE_SIZE (128 * 1024) 29 | 30 | // clang-format off 31 | enum nv_mem_kind 32 | { 33 | NV_MEM_KIND_PITCH = 0, 34 | NV_MEM_KIND_C32_2CRA = 0xdb, 35 | NV_MEM_KIND_GENERIC_16Bx2 = 0xfe, 36 | }; 37 | 38 | enum tegra_map_type { 39 | TEGRA_READ_TILED_BUFFER = 0, 40 | TEGRA_WRITE_TILED_BUFFER = 1, 41 | }; 42 | // clang-format on 43 | 44 | struct tegra_private_map_data { 45 | void *tiled; 46 | void *untiled; 47 | }; 48 | 49 | static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 }; 50 | 51 | static int compute_block_height_log2(int height) 52 | { 53 | int block_height_log2 = NV_DEFAULT_BLOCK_HEIGHT_LOG2; 54 | 55 | if (block_height_log2 > 0) { 56 | /* Shrink, if a smaller block height could cover the whole 57 | * surface height. */ 58 | int proposed = NV_BLOCKLINEAR_GOB_HEIGHT << (block_height_log2 - 1); 59 | while (proposed >= height) { 60 | block_height_log2--; 61 | if (block_height_log2 == 0) 62 | break; 63 | proposed /= 2; 64 | } 65 | } 66 | return block_height_log2; 67 | } 68 | 69 | static void compute_layout_blocklinear(int width, int height, int format, enum nv_mem_kind *kind, 70 | uint32_t *block_height_log2, uint32_t *stride, 71 | uint32_t *size) 72 | { 73 | int pitch = drv_stride_from_format(format, width, 0); 74 | 75 | /* Align to blocklinear blocks. */ 76 | pitch = ALIGN(pitch, NV_BLOCKLINEAR_GOB_WIDTH); 77 | 78 | /* Compute padded height. */ 79 | *block_height_log2 = compute_block_height_log2(height); 80 | int block_height = 1 << *block_height_log2; 81 | int padded_height = ALIGN(height, NV_BLOCKLINEAR_GOB_HEIGHT * block_height); 82 | 83 | int bytes = pitch * padded_height; 84 | 85 | /* Pad the allocation to the preferred page size. 86 | * This will reduce the required page table size (see discussion in NV 87 | * bug 1321091), and also acts as a WAR for NV bug 1325421. 88 | */ 89 | bytes = ALIGN(bytes, NV_PREFERRED_PAGE_SIZE); 90 | 91 | *kind = NV_MEM_KIND_C32_2CRA; 92 | *stride = pitch; 93 | *size = bytes; 94 | } 95 | 96 | static void compute_layout_linear(int width, int height, int format, uint32_t *stride, 97 | uint32_t *size) 98 | { 99 | *stride = ALIGN(drv_stride_from_format(format, width, 0), 64); 100 | *size = *stride * height; 101 | } 102 | 103 | static void transfer_tile(struct bo *bo, uint8_t *tiled, uint8_t *untiled, enum tegra_map_type type, 104 | uint32_t bytes_per_pixel, uint32_t gob_top, uint32_t gob_left, 105 | uint32_t gob_size_pixels, uint8_t *tiled_last) 106 | { 107 | uint8_t *tmp; 108 | uint32_t x, y, k; 109 | for (k = 0; k < gob_size_pixels; k++) { 110 | /* 111 | * Given the kth pixel starting from the tile specified by 112 | * gob_top and gob_left, unswizzle to get the standard (x, y) 113 | * representation. 114 | */ 115 | x = gob_left + (((k >> 3) & 8) | ((k >> 1) & 4) | (k & 3)); 116 | y = gob_top + ((k >> 7 << 3) | ((k >> 3) & 6) | ((k >> 2) & 1)); 117 | 118 | if (tiled >= tiled_last) 119 | return; 120 | 121 | if (x >= bo->width || y >= bo->height) { 122 | tiled += bytes_per_pixel; 123 | continue; 124 | } 125 | 126 | tmp = untiled + y * bo->strides[0] + x * bytes_per_pixel; 127 | 128 | if (type == TEGRA_READ_TILED_BUFFER) 129 | memcpy(tmp, tiled, bytes_per_pixel); 130 | else if (type == TEGRA_WRITE_TILED_BUFFER) 131 | memcpy(tiled, tmp, bytes_per_pixel); 132 | 133 | /* Move on to next pixel. */ 134 | tiled += bytes_per_pixel; 135 | } 136 | } 137 | 138 | static void transfer_tiled_memory(struct bo *bo, uint8_t *tiled, uint8_t *untiled, 139 | enum tegra_map_type type) 140 | { 141 | uint32_t gob_width, gob_height, gob_size_bytes, gob_size_pixels, gob_count_x, gob_count_y, 142 | gob_top, gob_left; 143 | uint32_t i, j, offset; 144 | uint8_t *tmp, *tiled_last; 145 | uint32_t bytes_per_pixel = drv_stride_from_format(bo->format, 1, 0); 146 | 147 | /* 148 | * The blocklinear format consists of 8*(2^n) x 64 byte sized tiles, 149 | * where 0 <= n <= 4. 150 | */ 151 | gob_width = DIV_ROUND_UP(NV_BLOCKLINEAR_GOB_WIDTH, bytes_per_pixel); 152 | gob_height = NV_BLOCKLINEAR_GOB_HEIGHT * (1 << NV_DEFAULT_BLOCK_HEIGHT_LOG2); 153 | /* Calculate the height from maximum possible gob height */ 154 | while (gob_height > NV_BLOCKLINEAR_GOB_HEIGHT && gob_height >= 2 * bo->height) 155 | gob_height /= 2; 156 | 157 | gob_size_bytes = gob_height * NV_BLOCKLINEAR_GOB_WIDTH; 158 | gob_size_pixels = gob_height * gob_width; 159 | 160 | gob_count_x = DIV_ROUND_UP(bo->strides[0], NV_BLOCKLINEAR_GOB_WIDTH); 161 | gob_count_y = DIV_ROUND_UP(bo->height, gob_height); 162 | 163 | tiled_last = tiled + bo->total_size; 164 | 165 | offset = 0; 166 | for (j = 0; j < gob_count_y; j++) { 167 | gob_top = j * gob_height; 168 | for (i = 0; i < gob_count_x; i++) { 169 | tmp = tiled + offset; 170 | gob_left = i * gob_width; 171 | 172 | transfer_tile(bo, tmp, untiled, type, bytes_per_pixel, gob_top, gob_left, 173 | gob_size_pixels, tiled_last); 174 | 175 | offset += gob_size_bytes; 176 | } 177 | } 178 | } 179 | 180 | static int tegra_init(struct driver *drv) 181 | { 182 | int ret; 183 | struct format_metadata metadata; 184 | uint64_t use_flags = BO_USE_RENDER_MASK; 185 | 186 | metadata.tiling = NV_MEM_KIND_PITCH; 187 | metadata.priority = 1; 188 | metadata.modifier = DRM_FORMAT_MOD_LINEAR; 189 | 190 | ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), 191 | &metadata, use_flags); 192 | if (ret) 193 | return ret; 194 | 195 | drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT); 196 | drv_modify_combination(drv, DRM_FORMAT_ARGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT); 197 | 198 | use_flags &= ~BO_USE_SW_WRITE_OFTEN; 199 | use_flags &= ~BO_USE_SW_READ_OFTEN; 200 | use_flags &= ~BO_USE_LINEAR; 201 | 202 | metadata.tiling = NV_MEM_KIND_C32_2CRA; 203 | metadata.priority = 2; 204 | 205 | ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), 206 | &metadata, use_flags); 207 | if (ret) 208 | return ret; 209 | 210 | drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_SCANOUT); 211 | drv_modify_combination(drv, DRM_FORMAT_ARGB8888, &metadata, BO_USE_SCANOUT); 212 | return 0; 213 | } 214 | 215 | static int tegra_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, 216 | uint64_t use_flags) 217 | { 218 | uint32_t size, stride, block_height_log2 = 0; 219 | enum nv_mem_kind kind = NV_MEM_KIND_PITCH; 220 | struct drm_tegra_gem_create gem_create; 221 | int ret; 222 | 223 | if (use_flags & 224 | (BO_USE_CURSOR | BO_USE_LINEAR | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN)) 225 | compute_layout_linear(width, height, format, &stride, &size); 226 | else 227 | compute_layout_blocklinear(width, height, format, &kind, &block_height_log2, 228 | &stride, &size); 229 | 230 | memset(&gem_create, 0, sizeof(gem_create)); 231 | gem_create.size = size; 232 | gem_create.flags = 0; 233 | 234 | ret = drmIoctl(bo->drv->fd, DRM_IOCTL_TEGRA_GEM_CREATE, &gem_create); 235 | if (ret) { 236 | fprintf(stderr, "drv: DRM_IOCTL_TEGRA_GEM_CREATE failed (size=%zu)\n", size); 237 | return ret; 238 | } 239 | 240 | bo->handles[0].u32 = gem_create.handle; 241 | bo->offsets[0] = 0; 242 | bo->total_size = bo->sizes[0] = size; 243 | bo->strides[0] = stride; 244 | 245 | if (kind != NV_MEM_KIND_PITCH) { 246 | struct drm_tegra_gem_set_tiling gem_tile; 247 | 248 | memset(&gem_tile, 0, sizeof(gem_tile)); 249 | gem_tile.handle = bo->handles[0].u32; 250 | gem_tile.mode = DRM_TEGRA_GEM_TILING_MODE_BLOCK; 251 | gem_tile.value = block_height_log2; 252 | 253 | ret = drmCommandWriteRead(bo->drv->fd, DRM_TEGRA_GEM_SET_TILING, &gem_tile, 254 | sizeof(gem_tile)); 255 | if (ret < 0) { 256 | drv_gem_bo_destroy(bo); 257 | return ret; 258 | } 259 | 260 | /* Encode blocklinear parameters for EGLImage creation. */ 261 | bo->tiling = (kind & 0xff) | ((block_height_log2 & 0xf) << 8); 262 | bo->format_modifiers[0] = fourcc_mod_code(NV, bo->tiling); 263 | } 264 | 265 | return 0; 266 | } 267 | 268 | static int tegra_bo_import(struct bo *bo, struct drv_import_fd_data *data) 269 | { 270 | int ret; 271 | struct drm_tegra_gem_get_tiling gem_get_tiling; 272 | 273 | ret = drv_prime_bo_import(bo, data); 274 | if (ret) 275 | return ret; 276 | 277 | /* TODO(gsingh): export modifiers and get rid of backdoor tiling. */ 278 | memset(&gem_get_tiling, 0, sizeof(gem_get_tiling)); 279 | gem_get_tiling.handle = bo->handles[0].u32; 280 | 281 | ret = drmIoctl(bo->drv->fd, DRM_IOCTL_TEGRA_GEM_GET_TILING, &gem_get_tiling); 282 | if (ret) { 283 | drv_gem_bo_destroy(bo); 284 | return ret; 285 | } 286 | 287 | /* NOTE(djmk): we only know about one tiled format, so if our drmIoctl call tells us we are 288 | tiled, assume it is this format (NV_MEM_KIND_C32_2CRA) otherwise linear (KIND_PITCH). */ 289 | if (gem_get_tiling.mode == DRM_TEGRA_GEM_TILING_MODE_PITCH) { 290 | bo->tiling = NV_MEM_KIND_PITCH; 291 | } else if (gem_get_tiling.mode == DRM_TEGRA_GEM_TILING_MODE_BLOCK) { 292 | bo->tiling = NV_MEM_KIND_C32_2CRA; 293 | } else { 294 | fprintf(stderr, "tegra_bo_import: unknown tile format %d", gem_get_tiling.mode); 295 | drv_gem_bo_destroy(bo); 296 | assert(0); 297 | } 298 | 299 | bo->format_modifiers[0] = fourcc_mod_code(NV, bo->tiling); 300 | return 0; 301 | } 302 | 303 | static void *tegra_bo_map(struct bo *bo, struct map_info *data, size_t plane, uint32_t map_flags) 304 | { 305 | int ret; 306 | struct drm_tegra_gem_mmap gem_map; 307 | struct tegra_private_map_data *priv; 308 | 309 | memset(&gem_map, 0, sizeof(gem_map)); 310 | gem_map.handle = bo->handles[0].u32; 311 | 312 | ret = drmCommandWriteRead(bo->drv->fd, DRM_TEGRA_GEM_MMAP, &gem_map, sizeof(gem_map)); 313 | if (ret < 0) { 314 | fprintf(stderr, "drv: DRM_TEGRA_GEM_MMAP failed\n"); 315 | return MAP_FAILED; 316 | } 317 | 318 | void *addr = mmap(0, bo->total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd, 319 | gem_map.offset); 320 | data->length = bo->total_size; 321 | if ((bo->tiling & 0xFF) == NV_MEM_KIND_C32_2CRA && addr != MAP_FAILED) { 322 | priv = calloc(1, sizeof(*priv)); 323 | priv->untiled = calloc(1, bo->total_size); 324 | priv->tiled = addr; 325 | data->priv = priv; 326 | transfer_tiled_memory(bo, priv->tiled, priv->untiled, TEGRA_READ_TILED_BUFFER); 327 | addr = priv->untiled; 328 | } 329 | 330 | return addr; 331 | } 332 | 333 | static int tegra_bo_unmap(struct bo *bo, struct map_info *data) 334 | { 335 | if (data->priv) { 336 | struct tegra_private_map_data *priv = data->priv; 337 | data->addr = priv->tiled; 338 | free(priv->untiled); 339 | free(priv); 340 | data->priv = NULL; 341 | } 342 | 343 | return munmap(data->addr, data->length); 344 | } 345 | 346 | static int tegra_bo_flush(struct bo *bo, struct map_info *data) 347 | { 348 | struct tegra_private_map_data *priv = data->priv; 349 | 350 | if (priv && (data->map_flags & BO_MAP_WRITE)) 351 | transfer_tiled_memory(bo, priv->tiled, priv->untiled, TEGRA_WRITE_TILED_BUFFER); 352 | 353 | return 0; 354 | } 355 | 356 | struct backend backend_tegra = { 357 | .name = "tegra", 358 | .init = tegra_init, 359 | .bo_create = tegra_bo_create, 360 | .bo_destroy = drv_gem_bo_destroy, 361 | .bo_import = tegra_bo_import, 362 | .bo_map = tegra_bo_map, 363 | .bo_unmap = tegra_bo_unmap, 364 | .bo_flush = tegra_bo_flush, 365 | }; 366 | 367 | #endif 368 | -------------------------------------------------------------------------------- /travisci/resources/minigbm-install.tar.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/minigbm/10d9a651375efa3592ab95431783984c28a30ad4/travisci/resources/minigbm-install.tar.bz2 -------------------------------------------------------------------------------- /udl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #include "drv_priv.h" 8 | #include "helpers.h" 9 | #include "util.h" 10 | 11 | static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 }; 12 | 13 | static int udl_init(struct driver *drv) 14 | { 15 | int ret; 16 | ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), 17 | &LINEAR_METADATA, BO_USE_RENDER_MASK); 18 | if (ret) 19 | return ret; 20 | 21 | return drv_modify_linear_combinations(drv); 22 | } 23 | 24 | struct backend backend_udl = { 25 | .name = "udl", 26 | .init = udl_init, 27 | .bo_create = drv_dumb_bo_create, 28 | .bo_destroy = drv_dumb_bo_destroy, 29 | .bo_import = drv_prime_bo_import, 30 | .bo_map = drv_dumb_bo_map, 31 | .bo_unmap = drv_bo_munmap, 32 | }; 33 | -------------------------------------------------------------------------------- /util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifndef UTIL_H 8 | #define UTIL_H 9 | 10 | #define MAX(A, B) ((A) > (B) ? (A) : (B)) 11 | #define ARRAY_SIZE(A) (sizeof(A) / sizeof(*(A))) 12 | #define PUBLIC __attribute__((visibility("default"))) 13 | #define ALIGN(A, B) (((A) + (B)-1) / (B) * (B)) 14 | #define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d)) 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /vc4.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #ifdef DRV_VC4 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "drv_priv.h" 16 | #include "helpers.h" 17 | #include "util.h" 18 | 19 | static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_RGB565, 20 | DRM_FORMAT_XRGB8888 }; 21 | 22 | static int vc4_init(struct driver *drv) 23 | { 24 | int ret; 25 | ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), 26 | &LINEAR_METADATA, BO_USE_RENDER_MASK); 27 | if (ret) 28 | return ret; 29 | 30 | return drv_modify_linear_combinations(drv); 31 | } 32 | 33 | static int vc4_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, 34 | uint64_t use_flags) 35 | { 36 | int ret; 37 | size_t plane; 38 | uint32_t stride; 39 | struct drm_vc4_create_bo bo_create; 40 | 41 | /* 42 | * Since the ARM L1 cache line size is 64 bytes, align to that as a 43 | * performance optimization. 44 | */ 45 | stride = drv_stride_from_format(format, width, 0); 46 | stride = ALIGN(stride, 64); 47 | drv_bo_from_format(bo, stride, height, format); 48 | 49 | memset(&bo_create, 0, sizeof(bo_create)); 50 | bo_create.size = bo->total_size; 51 | 52 | ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VC4_CREATE_BO, &bo_create); 53 | if (ret) { 54 | fprintf(stderr, "drv: DRM_IOCTL_VC4_GEM_CREATE failed (size=%zu)\n", 55 | bo->total_size); 56 | return ret; 57 | } 58 | 59 | for (plane = 0; plane < bo->num_planes; plane++) 60 | bo->handles[plane].u32 = bo_create.handle; 61 | 62 | return 0; 63 | } 64 | 65 | static void *vc4_bo_map(struct bo *bo, struct map_info *data, size_t plane, uint32_t map_flags) 66 | { 67 | int ret; 68 | struct drm_vc4_mmap_bo bo_map; 69 | 70 | memset(&bo_map, 0, sizeof(bo_map)); 71 | bo_map.handle = bo->handles[0].u32; 72 | 73 | ret = drmCommandWriteRead(bo->drv->fd, DRM_VC4_MMAP_BO, &bo_map, sizeof(bo_map)); 74 | if (ret) { 75 | fprintf(stderr, "drv: DRM_VC4_MMAP_BO failed\n"); 76 | return MAP_FAILED; 77 | } 78 | 79 | data->length = bo->total_size; 80 | return mmap(0, bo->total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd, 81 | bo_map.offset); 82 | } 83 | 84 | struct backend backend_vc4 = { 85 | .name = "vc4", 86 | .init = vc4_init, 87 | .bo_create = vc4_bo_create, 88 | .bo_import = drv_prime_bo_import, 89 | .bo_destroy = drv_gem_bo_destroy, 90 | .bo_map = vc4_bo_map, 91 | .bo_unmap = drv_bo_munmap, 92 | }; 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /vgem.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #include "drv_priv.h" 8 | #include "helpers.h" 9 | #include "util.h" 10 | 11 | #define MESA_LLVMPIPE_TILE_ORDER 6 12 | #define MESA_LLVMPIPE_TILE_SIZE (1 << MESA_LLVMPIPE_TILE_ORDER) 13 | 14 | static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888, 15 | DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888, 16 | DRM_FORMAT_XRGB8888 }; 17 | 18 | static const uint32_t texture_source_formats[] = { DRM_FORMAT_R8, DRM_FORMAT_YVU420, 19 | DRM_FORMAT_YVU420_ANDROID }; 20 | 21 | static int vgem_init(struct driver *drv) 22 | { 23 | int ret; 24 | ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), 25 | &LINEAR_METADATA, BO_USE_RENDER_MASK); 26 | if (ret) 27 | return ret; 28 | 29 | ret = drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats), 30 | &LINEAR_METADATA, BO_USE_TEXTURE_MASK); 31 | if (ret) 32 | return ret; 33 | 34 | return drv_modify_linear_combinations(drv); 35 | } 36 | 37 | static int vgem_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, 38 | uint64_t flags) 39 | { 40 | width = ALIGN(width, MESA_LLVMPIPE_TILE_SIZE); 41 | height = ALIGN(height, MESA_LLVMPIPE_TILE_SIZE); 42 | 43 | /* HAL_PIXEL_FORMAT_YV12 requires that the buffer's height not be aligned. */ 44 | if (bo->format == DRM_FORMAT_YVU420_ANDROID) 45 | height = bo->height; 46 | 47 | return drv_dumb_bo_create(bo, width, height, format, flags); 48 | } 49 | 50 | static uint32_t vgem_resolve_format(uint32_t format, uint64_t flags) 51 | { 52 | switch (format) { 53 | case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED: 54 | /*HACK: See b/28671744 */ 55 | return DRM_FORMAT_XBGR8888; 56 | case DRM_FORMAT_FLEX_YCbCr_420_888: 57 | return DRM_FORMAT_YVU420; 58 | default: 59 | return format; 60 | } 61 | } 62 | 63 | struct backend backend_vgem = { 64 | .name = "vgem", 65 | .init = vgem_init, 66 | .bo_create = vgem_bo_create, 67 | .bo_destroy = drv_dumb_bo_destroy, 68 | .bo_import = drv_prime_bo_import, 69 | .bo_map = drv_dumb_bo_map, 70 | .bo_unmap = drv_bo_munmap, 71 | .resolve_format = vgem_resolve_format, 72 | }; 73 | -------------------------------------------------------------------------------- /virtio_gpu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Chromium OS Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style license that can be 4 | * found in the LICENSE file. 5 | */ 6 | 7 | #include "drv_priv.h" 8 | #include "helpers.h" 9 | #include "util.h" 10 | 11 | #define MESA_LLVMPIPE_TILE_ORDER 6 12 | #define MESA_LLVMPIPE_TILE_SIZE (1 << MESA_LLVMPIPE_TILE_ORDER) 13 | 14 | static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888, 15 | DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888, 16 | DRM_FORMAT_XRGB8888 }; 17 | 18 | static const uint32_t texture_source_formats[] = { DRM_FORMAT_R8, DRM_FORMAT_YVU420, 19 | DRM_FORMAT_YVU420_ANDROID }; 20 | 21 | static int virtio_gpu_init(struct driver *drv) 22 | { 23 | int ret; 24 | ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), 25 | &LINEAR_METADATA, BO_USE_RENDER_MASK); 26 | if (ret) 27 | return ret; 28 | 29 | ret = drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats), 30 | &LINEAR_METADATA, BO_USE_TEXTURE_MASK); 31 | if (ret) 32 | return ret; 33 | 34 | return drv_modify_linear_combinations(drv); 35 | } 36 | 37 | static int virtio_gpu_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, 38 | uint64_t use_flags) 39 | { 40 | width = ALIGN(width, MESA_LLVMPIPE_TILE_SIZE); 41 | height = ALIGN(height, MESA_LLVMPIPE_TILE_SIZE); 42 | 43 | /* HAL_PIXEL_FORMAT_YV12 requires that the buffer's height not be aligned. */ 44 | if (bo->format == DRM_FORMAT_YVU420_ANDROID) 45 | height = bo->height; 46 | 47 | return drv_dumb_bo_create(bo, width, height, format, use_flags); 48 | } 49 | 50 | static uint32_t virtio_gpu_resolve_format(uint32_t format, uint64_t use_flags) 51 | { 52 | switch (format) { 53 | case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED: 54 | /*HACK: See b/28671744 */ 55 | return DRM_FORMAT_XBGR8888; 56 | case DRM_FORMAT_FLEX_YCbCr_420_888: 57 | return DRM_FORMAT_YVU420; 58 | default: 59 | return format; 60 | } 61 | } 62 | 63 | struct backend backend_virtio_gpu = { 64 | .name = "virtio_gpu", 65 | .init = virtio_gpu_init, 66 | .bo_create = virtio_gpu_bo_create, 67 | .bo_destroy = drv_dumb_bo_destroy, 68 | .bo_import = drv_prime_bo_import, 69 | .bo_map = drv_dumb_bo_map, 70 | .bo_unmap = drv_bo_munmap, 71 | .resolve_format = virtio_gpu_resolve_format, 72 | }; 73 | --------------------------------------------------------------------------------