diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-11-20 10:33:36 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-11-22 11:45:12 +0000 |
commit | be59a35641616a4cf23c4a13fa0632624b021c1b (patch) | |
tree | 9da183258bdf9cc413f7562079d25ace6955467f /chromium/third_party/minigbm | |
parent | d702e4b6a64574e97fc7df8fe3238cde70242080 (diff) | |
download | qtwebengine-chromium-be59a35641616a4cf23c4a13fa0632624b021c1b.tar.gz |
BASELINE: Update Chromium to 62.0.3202.101
Change-Id: I2d5eca8117600df6d331f6166ab24d943d9814ac
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/third_party/minigbm')
27 files changed, 502 insertions, 211 deletions
diff --git a/chromium/third_party/minigbm/src/Makefile b/chromium/third_party/minigbm/src/Makefile index 32cbb572c46..482e074a232 100644 --- a/chromium/third_party/minigbm/src/Makefile +++ b/chromium/third_party/minigbm/src/Makefile @@ -22,6 +22,9 @@ endif ifdef DRV_I915 CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_intel) endif +ifdef DRV_RADEON + CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_radeon) +endif ifdef DRV_ROCKCHIP CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_rockchip) endif diff --git a/chromium/third_party/minigbm/src/amdgpu.c b/chromium/third_party/minigbm/src/amdgpu.c index ee05009a36a..ff1336dbc75 100644 --- a/chromium/third_party/minigbm/src/amdgpu.c +++ b/chromium/third_party/minigbm/src/amdgpu.c @@ -400,7 +400,7 @@ static int amdgpu_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint return ret; } -static void *amdgpu_bo_map(struct bo *bo, struct map_info *data, size_t plane) +static void *amdgpu_bo_map(struct bo *bo, struct map_info *data, size_t plane, int prot) { int ret; union drm_amdgpu_gem_mmap gem_map; @@ -415,11 +415,10 @@ static void *amdgpu_bo_map(struct bo *bo, struct map_info *data, size_t plane) } data->length = bo->total_size; - return mmap(0, bo->total_size, PROT_READ | PROT_WRITE, MAP_SHARED, bo->drv->fd, - gem_map.out.addr_ptr); + return mmap(0, bo->total_size, prot, MAP_SHARED, bo->drv->fd, gem_map.out.addr_ptr); } -static uint32_t amdgpu_resolve_format(uint32_t format) +static uint32_t amdgpu_resolve_format(uint32_t format, uint64_t usage) { switch (format) { case DRM_FORMAT_FLEX_YCbCr_420_888: diff --git a/chromium/third_party/minigbm/src/cros_gralloc/Makefile b/chromium/third_party/minigbm/src/cros_gralloc/Makefile index 9c23e7b24c0..17e884fb210 100644 --- a/chromium/third_party/minigbm/src/cros_gralloc/Makefile +++ b/chromium/third_party/minigbm/src/cros_gralloc/Makefile @@ -19,7 +19,7 @@ LIBDRM_LIBS := $(shell $(PKG_CONFIG) --libs libdrm) CPPFLAGS += -Wall -fPIC -Werror -flto $(LIBDRM_CFLAGS) CXXFLAGS += -std=c++14 CFLAGS += -std=c99 -LIBS += -shared -lcutils -lhardware $(LIBDRM_LIBS) +LIBS += -shared -lcutils -lhardware -lsync $(LIBDRM_LIBS) OBJS = $(foreach source, $(SOURCES), $(addsuffix .o, $(basename $(source)))) diff --git a/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_buffer.cc b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_buffer.cc index 1ef7278e1fa..b6da605515e 100644 --- a/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_buffer.cc +++ b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_buffer.cc @@ -46,44 +46,45 @@ int32_t cros_gralloc_buffer::decrease_refcount() int32_t cros_gralloc_buffer::lock(uint64_t flags, uint8_t *addr[DRV_MAX_PLANES]) { + void *vaddr = nullptr; + + memset(addr, 0, DRV_MAX_PLANES * sizeof(*addr)); + /* * Gralloc consumers don't support more than one kernel buffer per buffer object yet, so * just use the first kernel buffer. */ if (drv_num_buffers_per_bo(bo_) != 1) { cros_gralloc_error("Can only support one buffer per bo."); - return CROS_GRALLOC_ERROR_NO_RESOURCES; + return -EINVAL; } if (flags) { - void *vaddr; if (lock_data_[0]) { vaddr = lock_data_[0]->addr; } else { vaddr = drv_bo_map(bo_, 0, 0, drv_bo_get_width(bo_), drv_bo_get_height(bo_), - 0, &lock_data_[0], 0); + BO_TRANSFER_READ_WRITE, &lock_data_[0], 0); } if (vaddr == MAP_FAILED) { cros_gralloc_error("Mapping failed."); - return CROS_GRALLOC_ERROR_UNSUPPORTED; + return -EFAULT; } - - addr[0] = static_cast<uint8_t *>(vaddr); } for (uint32_t plane = 0; plane < num_planes_; plane++) - addr[plane] = addr[0] + drv_bo_get_plane_offset(bo_, plane); + addr[plane] = static_cast<uint8_t *>(vaddr) + drv_bo_get_plane_offset(bo_, plane); lockcount_++; - return CROS_GRALLOC_ERROR_NONE; + return 0; } int32_t cros_gralloc_buffer::unlock() { if (lockcount_ <= 0) { cros_gralloc_error("Buffer was not locked."); - return CROS_GRALLOC_ERROR_UNSUPPORTED; + return -EINVAL; } if (!--lockcount_) { @@ -93,5 +94,5 @@ int32_t cros_gralloc_buffer::unlock() } } - return CROS_GRALLOC_ERROR_NONE; + return 0; } diff --git a/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_driver.cc b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_driver.cc index 603e96d5a7d..f6e65b7bfb2 100644 --- a/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_driver.cc +++ b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_driver.cc @@ -67,18 +67,19 @@ int32_t cros_gralloc_driver::init() drmFreeVersion(version); drv_ = drv_create(fd); if (drv_) - return CROS_GRALLOC_ERROR_NONE; + return 0; } } - return CROS_GRALLOC_ERROR_NO_RESOURCES; + return -ENODEV; } bool cros_gralloc_driver::is_supported(const struct cros_gralloc_buffer_descriptor *descriptor) { struct combination *combo; - combo = drv_get_combination(drv_, drv_resolve_format(drv_, descriptor->drm_format), - descriptor->drv_usage); + uint32_t resolved_format; + resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->drv_usage); + combo = drv_get_combination(drv_, resolved_format, descriptor->drv_usage); return (combo != nullptr); } @@ -88,15 +89,17 @@ int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descripto uint32_t id; uint64_t mod; size_t num_planes; + uint32_t resolved_format; struct bo *bo; struct cros_gralloc_handle *hnd; - bo = drv_bo_create(drv_, descriptor->width, descriptor->height, - drv_resolve_format(drv_, descriptor->drm_format), descriptor->drv_usage); + resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->drv_usage); + bo = drv_bo_create(drv_, descriptor->width, descriptor->height, resolved_format, + descriptor->drv_usage); if (!bo) { cros_gralloc_error("Failed to create bo."); - return CROS_GRALLOC_ERROR_NO_RESOURCES; + return -ENOMEM; } /* @@ -107,7 +110,7 @@ int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descripto if (drv_num_buffers_per_bo(bo) != 1) { drv_bo_destroy(bo); cros_gralloc_error("Can only support one buffer per bo."); - return CROS_GRALLOC_ERROR_NO_RESOURCES; + return -EINVAL; } hnd = new cros_gralloc_handle(); @@ -131,6 +134,8 @@ int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descripto hnd->width = drv_bo_get_width(bo); hnd->height = drv_bo_get_height(bo); hnd->format = drv_bo_get_format(bo); + hnd->flags[0] = static_cast<uint32_t>(descriptor->drv_usage >> 32); + hnd->flags[1] = static_cast<uint32_t>(descriptor->drv_usage); hnd->pixel_stride = drv_bo_get_stride_in_pixels(bo); hnd->magic = cros_gralloc_magic; hnd->droid_format = descriptor->droid_format; @@ -143,7 +148,7 @@ int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descripto buffers_.emplace(id, buffer); handles_.emplace(hnd, std::make_pair(buffer, 1)); *out_handle = &hnd->base; - return CROS_GRALLOC_ERROR_NONE; + return 0; } int32_t cros_gralloc_driver::retain(buffer_handle_t handle) @@ -154,19 +159,19 @@ int32_t cros_gralloc_driver::retain(buffer_handle_t handle) auto hnd = cros_gralloc_convert_handle(handle); if (!hnd) { cros_gralloc_error("Invalid handle."); - return CROS_GRALLOC_ERROR_BAD_HANDLE; + return -EINVAL; } auto buffer = get_buffer(hnd); if (buffer) { handles_[hnd].second++; buffer->increase_refcount(); - return CROS_GRALLOC_ERROR_NONE; + return 0; } if (drmPrimeFDToHandle(drv_get_fd(drv_), hnd->fds[0], &id)) { cros_gralloc_error("drmPrimeFDToHandle failed."); - return CROS_GRALLOC_ERROR_BAD_HANDLE; + return -errno; } if (buffers_.count(id)) { @@ -178,6 +183,8 @@ int32_t cros_gralloc_driver::retain(buffer_handle_t handle) data.format = hnd->format; data.width = hnd->width; data.height = hnd->height; + data.flags = static_cast<uint64_t>(hnd->flags[0]) << 32; + data.flags |= hnd->flags[1]; memcpy(data.fds, hnd->fds, sizeof(data.fds)); memcpy(data.strides, hnd->strides, sizeof(data.strides)); @@ -191,7 +198,7 @@ int32_t cros_gralloc_driver::retain(buffer_handle_t handle) bo = drv_bo_import(drv_, &data); if (!bo) - return CROS_GRALLOC_ERROR_NO_RESOURCES; + return -EFAULT; id = drv_bo_get_plane_handle(bo, 0).u32; @@ -200,7 +207,7 @@ int32_t cros_gralloc_driver::retain(buffer_handle_t handle) } handles_.emplace(hnd, std::make_pair(buffer, 1)); - return CROS_GRALLOC_ERROR_NONE; + return 0; } int32_t cros_gralloc_driver::release(buffer_handle_t handle) @@ -210,13 +217,13 @@ int32_t cros_gralloc_driver::release(buffer_handle_t handle) auto hnd = cros_gralloc_convert_handle(handle); if (!hnd) { cros_gralloc_error("Invalid handle."); - return CROS_GRALLOC_ERROR_BAD_HANDLE; + return -EINVAL; } auto buffer = get_buffer(hnd); if (!buffer) { cros_gralloc_error("Invalid Reference."); - return CROS_GRALLOC_ERROR_BAD_HANDLE; + return -EINVAL; } if (!--handles_[hnd].second) @@ -227,50 +234,55 @@ int32_t cros_gralloc_driver::release(buffer_handle_t handle) delete buffer; } - return CROS_GRALLOC_ERROR_NONE; + return 0; } int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence, uint64_t flags, uint8_t *addr[DRV_MAX_PLANES]) { - std::lock_guard<std::mutex> lock(mutex_); + int32_t ret = cros_gralloc_sync_wait(acquire_fence); + if (ret) + return ret; + std::lock_guard<std::mutex> lock(mutex_); auto hnd = cros_gralloc_convert_handle(handle); if (!hnd) { cros_gralloc_error("Invalid handle."); - return CROS_GRALLOC_ERROR_BAD_HANDLE; + return -EINVAL; } auto buffer = get_buffer(hnd); if (!buffer) { cros_gralloc_error("Invalid Reference."); - return CROS_GRALLOC_ERROR_BAD_HANDLE; - } - - if (acquire_fence >= 0) { - cros_gralloc_error("Sync wait not yet supported."); - return CROS_GRALLOC_ERROR_UNSUPPORTED; + return -EINVAL; } return buffer->lock(flags, addr); } -int32_t cros_gralloc_driver::unlock(buffer_handle_t handle) +int32_t cros_gralloc_driver::unlock(buffer_handle_t handle, int32_t *release_fence) { std::lock_guard<std::mutex> lock(mutex_); auto hnd = cros_gralloc_convert_handle(handle); if (!hnd) { cros_gralloc_error("Invalid handle."); - return CROS_GRALLOC_ERROR_BAD_HANDLE; + return -EINVAL; } auto buffer = get_buffer(hnd); if (!buffer) { cros_gralloc_error("Invalid Reference."); - return CROS_GRALLOC_ERROR_BAD_HANDLE; + return -EINVAL; } + /* + * From the ANativeWindow::dequeueBuffer documentation: + * + * "A value of -1 indicates that the caller may access the buffer immediately without + * waiting on a fence." + */ + *release_fence = -1; return buffer->unlock(); } @@ -281,17 +293,17 @@ int32_t cros_gralloc_driver::get_backing_store(buffer_handle_t handle, uint64_t auto hnd = cros_gralloc_convert_handle(handle); if (!hnd) { cros_gralloc_error("Invalid handle."); - return CROS_GRALLOC_ERROR_BAD_HANDLE; + return -EINVAL; } auto buffer = get_buffer(hnd); if (!buffer) { cros_gralloc_error("Invalid Reference."); - return CROS_GRALLOC_ERROR_BAD_HANDLE; + return -EINVAL; } *out_store = static_cast<uint64_t>(buffer->get_id()); - return CROS_GRALLOC_ERROR_NONE; + return 0; } cros_gralloc_buffer *cros_gralloc_driver::get_buffer(cros_gralloc_handle_t hnd) diff --git a/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_driver.h b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_driver.h index 7b3b668f2cb..b8754977a40 100644 --- a/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_driver.h +++ b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_driver.h @@ -28,7 +28,7 @@ class cros_gralloc_driver int32_t lock(buffer_handle_t handle, int32_t acquire_fence, uint64_t flags, uint8_t *addr[DRV_MAX_PLANES]); - int32_t unlock(buffer_handle_t handle); + int32_t unlock(buffer_handle_t handle, int32_t *release_fence); int32_t get_backing_store(buffer_handle_t handle, uint64_t *out_store); diff --git a/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_handle.h b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_handle.h index e549675fc41..4cb554dc04a 100644 --- a/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_handle.h +++ b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_handle.h @@ -26,7 +26,8 @@ struct cros_gralloc_handle { uint32_t format_modifiers[2 * DRV_MAX_PLANES]; uint32_t width; uint32_t height; - uint32_t format; /* DRM format */ + uint32_t format; /* DRM format */ + uint32_t flags[2]; /* driver creation time flags */ uint32_t magic; uint32_t pixel_stride; int32_t droid_format; diff --git a/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_helpers.cc b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_helpers.cc index f0b667d2bc1..e662084bd9f 100644 --- a/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_helpers.cc +++ b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_helpers.cc @@ -8,6 +8,7 @@ #include <cstdlib> #include <cutils/log.h> +#include <sync/sync.h> uint32_t cros_gralloc_convert_format(int format) { @@ -54,6 +55,34 @@ cros_gralloc_handle_t cros_gralloc_convert_handle(buffer_handle_t handle) return hnd; } +int32_t cros_gralloc_sync_wait(int32_t acquire_fence) +{ + if (acquire_fence < 0) + return 0; + + /* + * Wait initially for 1000 ms, and then wait indefinitely. The SYNC_IOC_WAIT + * documentation states the caller waits indefinitely on the fence if timeout < 0. + */ + int err = sync_wait(acquire_fence, 1000); + if (err < 0) { + cros_gralloc_error("Timed out on sync wait, err = %s", strerror(errno)); + err = sync_wait(acquire_fence, -1); + if (err < 0) { + cros_gralloc_error("sync wait error = %s", strerror(errno)); + return -errno; + } + } + + err = close(acquire_fence); + if (err) { + cros_gralloc_error("Unable to close fence fd, err = %s", strerror(errno)); + return -errno; + } + + return 0; +} + void cros_gralloc_log(const char *prefix, const char *file, int line, const char *format, ...) { char buf[50]; diff --git a/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_helpers.h b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_helpers.h index f198dd9668d..cf90ec8cb1a 100644 --- a/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_helpers.h +++ b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_helpers.h @@ -22,6 +22,8 @@ uint32_t cros_gralloc_convert_format(int32_t format); cros_gralloc_handle_t cros_gralloc_convert_handle(buffer_handle_t handle); +int32_t cros_gralloc_sync_wait(int32_t acquire_fence); + __attribute__((format(printf, 4, 5))) void cros_gralloc_log(const char *prefix, const char *file, int line, const char *format, ...); diff --git a/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_types.h b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_types.h index b1938c89c45..2f6122e1324 100644 --- a/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_types.h +++ b/chromium/third_party/minigbm/src/cros_gralloc/cros_gralloc_types.h @@ -7,17 +7,6 @@ #ifndef CROS_GRALLOC_TYPES_H #define CROS_GRALLOC_TYPES_H -typedef enum { - CROS_GRALLOC_ERROR_NONE = 0, - CROS_GRALLOC_ERROR_BAD_DESCRIPTOR = 1, - CROS_GRALLOC_ERROR_BAD_HANDLE = 2, - CROS_GRALLOC_ERROR_BAD_VALUE = 3, - CROS_GRALLOC_ERROR_NOT_SHARED = 4, - CROS_GRALLOC_ERROR_NO_RESOURCES = 5, - CROS_GRALLOC_ERROR_UNDEFINED = 6, - CROS_GRALLOC_ERROR_UNSUPPORTED = 7, -} cros_gralloc_error_t; - struct cros_gralloc_buffer_descriptor { uint32_t width; uint32_t height; diff --git a/chromium/third_party/minigbm/src/cros_gralloc/gralloc0/gralloc0.cc b/chromium/third_party/minigbm/src/cros_gralloc/gralloc0/gralloc0.cc index 79d1113cc57..533f8cac099 100644 --- a/chromium/third_party/minigbm/src/cros_gralloc/gralloc0/gralloc0.cc +++ b/chromium/third_party/minigbm/src/cros_gralloc/gralloc0/gralloc0.cc @@ -13,6 +13,8 @@ struct gralloc0_module { gralloc_module_t base; std::unique_ptr<alloc_device_t> alloc; std::unique_ptr<cros_gralloc_driver> driver; + bool initialized; + std::mutex initialization_mutex; }; /* This enumeration must match the one in <gralloc_drm.h>. @@ -67,14 +69,11 @@ static int64_t gralloc0_convert_flags(int flags) /*HACK: See b/30054495 */ usage |= BO_USE_SW_READ_OFTEN; if (flags & GRALLOC_USAGE_HW_CAMERA_WRITE) - usage |= BO_USE_HW_CAMERA_WRITE; + usage |= BO_USE_CAMERA_WRITE; if (flags & GRALLOC_USAGE_HW_CAMERA_READ) - usage |= BO_USE_HW_CAMERA_READ; - if (flags & GRALLOC_USAGE_HW_CAMERA_ZSL) - usage |= BO_USE_HW_CAMERA_ZSL; + usage |= BO_USE_CAMERA_READ; if (flags & GRALLOC_USAGE_RENDERSCRIPT) - /* We use CPU for compute. */ - usage |= BO_USE_LINEAR; + usage |= BO_USE_RENDERSCRIPT; return usage; } @@ -103,9 +102,9 @@ static int gralloc0_alloc(alloc_device_t *dev, int w, int h, int format, int usa if (!supported) { cros_gralloc_error("Unsupported combination -- HAL format: %u, HAL flags: %u, " "drv_format: %4.4s, drv_flags: %llu", - format, usage, reinterpret_cast<char *>(descriptor.drm_format), + format, usage, reinterpret_cast<char *>(&descriptor.drm_format), static_cast<unsigned long long>(descriptor.drv_usage)); - return CROS_GRALLOC_ERROR_UNSUPPORTED; + return -EINVAL; } ret = mod->driver->allocate(&descriptor, handle); @@ -115,7 +114,7 @@ static int gralloc0_alloc(alloc_device_t *dev, int w, int h, int format, int usa auto hnd = cros_gralloc_convert_handle(*handle); *stride = hnd->pixel_stride; - return CROS_GRALLOC_ERROR_NONE; + return 0; } static int gralloc0_free(alloc_device_t *dev, buffer_handle_t handle) @@ -127,53 +126,64 @@ static int gralloc0_free(alloc_device_t *dev, buffer_handle_t handle) static int gralloc0_close(struct hw_device_t *dev) { /* Memory is freed by managed pointers on process close. */ - return CROS_GRALLOC_ERROR_NONE; + return 0; +} + +static int gralloc0_init(struct gralloc0_module *mod, bool initialize_alloc) +{ + std::lock_guard<std::mutex> lock(mod->initialization_mutex); + + if (mod->initialized) + return 0; + + mod->driver = std::make_unique<cros_gralloc_driver>(); + if (mod->driver->init()) { + cros_gralloc_error("Failed to initialize driver."); + return -ENODEV; + } + + if (initialize_alloc) { + mod->alloc = std::make_unique<alloc_device_t>(); + mod->alloc->alloc = gralloc0_alloc; + mod->alloc->free = gralloc0_free; + mod->alloc->common.tag = HARDWARE_DEVICE_TAG; + mod->alloc->common.version = 0; + mod->alloc->common.module = (hw_module_t *)mod; + mod->alloc->common.close = gralloc0_close; + } + + mod->initialized = true; + return 0; } static int gralloc0_open(const struct hw_module_t *mod, const char *name, struct hw_device_t **dev) { auto module = (struct gralloc0_module *)mod; - if (module->alloc) { + if (module->initialized) { *dev = &module->alloc->common; - return CROS_GRALLOC_ERROR_NONE; + return 0; } if (strcmp(name, GRALLOC_HARDWARE_GPU0)) { cros_gralloc_error("Incorrect device name - %s.", name); - return CROS_GRALLOC_ERROR_UNSUPPORTED; - } - - module->driver = std::make_unique<cros_gralloc_driver>(); - if (module->driver->init()) { - cros_gralloc_error("Failed to initialize driver."); - return CROS_GRALLOC_ERROR_NO_RESOURCES; + return -EINVAL; } - module->alloc = std::make_unique<alloc_device_t>(); - - module->alloc->alloc = gralloc0_alloc; - module->alloc->free = gralloc0_free; - module->alloc->common.tag = HARDWARE_DEVICE_TAG; - module->alloc->common.version = 0; - module->alloc->common.module = (hw_module_t *)mod; - module->alloc->common.close = gralloc0_close; + if (gralloc0_init(module, true)) + return -ENODEV; *dev = &module->alloc->common; - return CROS_GRALLOC_ERROR_NONE; + return 0; } static int gralloc0_register_buffer(struct gralloc_module_t const *module, buffer_handle_t handle) { auto mod = (struct gralloc0_module *)module; - if (!mod->driver) { - mod->driver = std::make_unique<cros_gralloc_driver>(); - if (mod->driver->init()) { - cros_gralloc_error("Failed to initialize driver."); - return CROS_GRALLOC_ERROR_NO_RESOURCES; - } - } + if (!mod->initialized) + if (gralloc0_init(mod, false)) + return -ENODEV; return mod->driver->retain(handle); } @@ -187,33 +197,22 @@ static int gralloc0_unregister_buffer(struct gralloc_module_t const *module, buf static int gralloc0_lock(struct gralloc_module_t const *module, buffer_handle_t handle, int usage, int l, int t, int w, int h, void **vaddr) { - int32_t ret, fence; - uint64_t flags; - uint8_t *addr[DRV_MAX_PLANES]; - auto mod = (struct gralloc0_module *)module; - - auto hnd = cros_gralloc_convert_handle(handle); - if (!hnd) { - cros_gralloc_error("Invalid handle."); - return CROS_GRALLOC_ERROR_BAD_HANDLE; - } - - if ((hnd->droid_format == HAL_PIXEL_FORMAT_YCbCr_420_888)) { - cros_gralloc_error("HAL_PIXEL_FORMAT_YCbCr_*_888 format not compatible."); - return CROS_GRALLOC_ERROR_BAD_HANDLE; - } - - fence = -1; - flags = gralloc0_convert_flags(usage); - ret = mod->driver->lock(handle, fence, flags, addr); - *vaddr = addr[0]; - return ret; + return module->lockAsync(module, handle, usage, l, t, w, h, vaddr, -1); } static int gralloc0_unlock(struct gralloc_module_t const *module, buffer_handle_t handle) { + int32_t fence_fd, ret; auto mod = (struct gralloc0_module *)module; - return mod->driver->unlock(handle); + ret = mod->driver->unlock(handle, &fence_fd); + if (ret) + return ret; + + ret = cros_gralloc_sync_wait(fence_fd); + if (ret) + return ret; + + return 0; } static int gralloc0_perform(struct gralloc_module_t const *module, int op, ...) @@ -232,17 +231,17 @@ static int gralloc0_perform(struct gralloc_module_t const *module, int op, ...) case GRALLOC_DRM_GET_BACKING_STORE: break; default: - return CROS_GRALLOC_ERROR_UNSUPPORTED; + return -EINVAL; } va_start(args, op); - ret = CROS_GRALLOC_ERROR_NONE; + ret = 0; handle = va_arg(args, buffer_handle_t); auto hnd = cros_gralloc_convert_handle(handle); if (!hnd) { cros_gralloc_error("Invalid handle."); - return CROS_GRALLOC_ERROR_BAD_HANDLE; + return -EINVAL; } switch (op) { @@ -265,7 +264,7 @@ static int gralloc0_perform(struct gralloc_module_t const *module, int op, ...) ret = mod->driver->get_backing_store(handle, out_store); break; default: - ret = CROS_GRALLOC_ERROR_UNSUPPORTED; + ret = -EINVAL; } va_end(args); @@ -276,26 +275,67 @@ static int gralloc0_perform(struct gralloc_module_t const *module, int op, ...) static int gralloc0_lock_ycbcr(struct gralloc_module_t const *module, buffer_handle_t handle, int usage, int l, int t, int w, int h, struct android_ycbcr *ycbcr) { + return module->lockAsync_ycbcr(module, handle, usage, l, t, w, h, ycbcr, -1); +} + +static int gralloc0_lock_async(struct gralloc_module_t const *module, buffer_handle_t handle, + int usage, int l, int t, int w, int h, void **vaddr, int fence_fd) +{ + int32_t ret; + uint64_t flags; + uint8_t *addr[DRV_MAX_PLANES]; + auto mod = (struct gralloc0_module *)module; + + auto hnd = cros_gralloc_convert_handle(handle); + if (!hnd) { + cros_gralloc_error("Invalid handle."); + return -EINVAL; + } + + if (hnd->droid_format == HAL_PIXEL_FORMAT_YCbCr_420_888) { + cros_gralloc_error("HAL_PIXEL_FORMAT_YCbCr_*_888 format not compatible."); + return -EINVAL; + } + + flags = gralloc0_convert_flags(usage); + ret = mod->driver->lock(handle, fence_fd, flags, addr); + *vaddr = addr[0]; + return ret; +} + +static int gralloc0_unlock_async(struct gralloc_module_t const *module, buffer_handle_t handle, + int *fence_fd) +{ + auto mod = (struct gralloc0_module *)module; + return mod->driver->unlock(handle, fence_fd); +} + +static int gralloc0_lock_async_ycbcr(struct gralloc_module_t const *module, buffer_handle_t handle, + int usage, int l, int t, int w, int h, + struct android_ycbcr *ycbcr, int fence_fd) +{ uint64_t flags; - int32_t fence, ret; + int32_t ret; uint8_t *addr[DRV_MAX_PLANES] = { nullptr, nullptr, nullptr, nullptr }; auto mod = (struct gralloc0_module *)module; auto hnd = cros_gralloc_convert_handle(handle); if (!hnd) { cros_gralloc_error("Invalid handle."); - return CROS_GRALLOC_ERROR_BAD_HANDLE; + return -EINVAL; } if ((hnd->droid_format != HAL_PIXEL_FORMAT_YCbCr_420_888) && - (hnd->droid_format != HAL_PIXEL_FORMAT_YV12)) { + (hnd->droid_format != HAL_PIXEL_FORMAT_YV12) && + (hnd->droid_format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)) { cros_gralloc_error("Non-YUV format not compatible."); - return CROS_GRALLOC_ERROR_BAD_HANDLE; + return -EINVAL; } - fence = -1; flags = gralloc0_convert_flags(usage); - ret = mod->driver->lock(handle, fence, flags, addr); + ret = mod->driver->lock(handle, fence_fd, flags, addr); + if (ret) + return ret; switch (hnd->format) { case DRM_FORMAT_NV12: @@ -316,13 +356,16 @@ static int gralloc0_lock_ycbcr(struct gralloc_module_t const *module, buffer_han ycbcr->chroma_step = 1; break; default: - return CROS_GRALLOC_ERROR_UNSUPPORTED; + module->unlock(module, handle); + return -EINVAL; } - return ret; + return 0; } -static struct hw_module_methods_t gralloc0_module_methods = {.open = gralloc0_open }; +// clang-format off +static struct hw_module_methods_t gralloc0_module_methods = { .open = gralloc0_open }; +// clang-format on struct gralloc0_module HAL_MODULE_INFO_SYM = { .base = @@ -330,7 +373,7 @@ struct gralloc0_module HAL_MODULE_INFO_SYM = { .common = { .tag = HARDWARE_MODULE_TAG, - .module_api_version = GRALLOC_MODULE_API_VERSION_0_2, + .module_api_version = GRALLOC_MODULE_API_VERSION_0_3, .hal_api_version = 0, .id = GRALLOC_HARDWARE_MODULE_ID, .name = "CrOS Gralloc", @@ -344,8 +387,12 @@ struct gralloc0_module HAL_MODULE_INFO_SYM = { .unlock = gralloc0_unlock, .perform = gralloc0_perform, .lock_ycbcr = gralloc0_lock_ycbcr, + .lockAsync = gralloc0_lock_async, + .unlockAsync = gralloc0_unlock_async, + .lockAsync_ycbcr = gralloc0_lock_async_ycbcr, }, .alloc = nullptr, .driver = nullptr, + .initialized = false, }; diff --git a/chromium/third_party/minigbm/src/drv.c b/chromium/third_party/minigbm/src/drv.c index bcc8cfaf3fd..10a63485ea5 100644 --- a/chromium/third_party/minigbm/src/drv.c +++ b/chromium/third_party/minigbm/src/drv.c @@ -37,6 +37,9 @@ extern struct backend backend_marvell; extern struct backend backend_mediatek; #endif extern struct backend backend_nouveau; +#ifdef DRV_RADEON +extern struct backend backend_radeon; +#endif #ifdef DRV_ROCKCHIP extern struct backend backend_rockchip; #endif @@ -79,6 +82,9 @@ static struct backend *drv_get_backend(int fd) &backend_mediatek, #endif &backend_nouveau, +#ifdef DRV_RADEON + &backend_radeon, +#endif #ifdef DRV_ROCKCHIP &backend_rockchip, #endif @@ -205,7 +211,8 @@ struct combination *drv_get_combination(struct driver *drv, uint32_t format, uin return best; } -struct bo *drv_bo_new(struct driver *drv, uint32_t width, uint32_t height, uint32_t format) +struct bo *drv_bo_new(struct driver *drv, uint32_t width, uint32_t height, uint32_t format, + uint64_t flags) { struct bo *bo; @@ -218,6 +225,7 @@ struct bo *drv_bo_new(struct driver *drv, uint32_t width, uint32_t height, uint3 bo->width = width; bo->height = height; bo->format = format; + bo->flags = flags; bo->num_planes = drv_num_planes_from_format(format); if (!bo->num_planes) { @@ -235,7 +243,7 @@ struct bo *drv_bo_create(struct driver *drv, uint32_t width, uint32_t height, ui size_t plane; struct bo *bo; - bo = drv_bo_new(drv, width, height, format); + bo = drv_bo_new(drv, width, height, format, flags); if (!bo) return NULL; @@ -269,7 +277,7 @@ struct bo *drv_bo_create_with_modifiers(struct driver *drv, uint32_t width, uint return NULL; } - bo = drv_bo_new(drv, width, height, format); + bo = drv_bo_new(drv, width, height, format, BO_USE_NONE); if (!bo) return NULL; @@ -295,6 +303,7 @@ void drv_bo_destroy(struct bo *bo) { size_t plane; uintptr_t total = 0; + size_t map_count = 0; struct driver *drv = bo->drv; pthread_mutex_lock(&drv->driver_lock); @@ -302,13 +311,24 @@ void drv_bo_destroy(struct bo *bo) for (plane = 0; plane < bo->num_planes; plane++) drv_decrement_reference_count(drv, bo, plane); - for (plane = 0; plane < bo->num_planes; plane++) + for (plane = 0; plane < bo->num_planes; plane++) { + void *ptr; + total += drv_get_reference_count(drv, bo, plane); + map_count += !drmHashLookup(bo->drv->map_table, bo->handles[plane].u32, &ptr); + } pthread_mutex_unlock(&drv->driver_lock); - if (total == 0) + if (total == 0) { + /* + * If we leak a reference to the GEM handle being freed here in the mapping table, + * we risk using the mapping table entry later for a completely different BO that + * gets the same handle. (See b/38250067.) + */ + assert(!map_count); bo->drv->backend->bo_destroy(bo); + } free(bo); } @@ -319,7 +339,7 @@ struct bo *drv_bo_import(struct driver *drv, struct drv_import_fd_data *data) size_t plane; struct bo *bo; - bo = drv_bo_new(drv, data->width, data->height, data->format); + bo = drv_bo_new(drv, data->width, data->height, data->format, data->flags); if (!bo) return NULL; @@ -348,11 +368,13 @@ void *drv_bo_map(struct bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t uint8_t *addr; size_t offset; struct map_info *data; + int prot; assert(width > 0); assert(height > 0); assert(x + width <= drv_bo_get_width(bo)); assert(y + height <= drv_bo_get_height(bo)); + assert(BO_TRANSFER_READ_WRITE & flags); pthread_mutex_lock(&bo->drv->driver_lock); @@ -363,7 +385,8 @@ void *drv_bo_map(struct bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t } data = calloc(1, sizeof(*data)); - addr = bo->drv->backend->bo_map(bo, data, plane); + prot = BO_TRANSFER_WRITE & flags ? PROT_WRITE | PROT_READ : PROT_READ; + addr = bo->drv->backend->bo_map(bo, data, plane, prot); if (addr == MAP_FAILED) { *map_data = NULL; free(data); @@ -479,10 +502,10 @@ uint32_t drv_bo_get_format(struct bo *bo) return bo->format; } -uint32_t drv_resolve_format(struct driver *drv, uint32_t format) +uint32_t drv_resolve_format(struct driver *drv, uint32_t format, uint64_t usage) { if (drv->backend->resolve_format) - return drv->backend->resolve_format(format); + return drv->backend->resolve_format(format, usage); return format; } diff --git a/chromium/third_party/minigbm/src/drv.h b/chromium/third_party/minigbm/src/drv.h index f478a665940..e4678a118e5 100644 --- a/chromium/third_party/minigbm/src/drv.h +++ b/chromium/third_party/minigbm/src/drv.h @@ -33,12 +33,17 @@ extern "C" { #define BO_USE_EXTERNAL_DISP (1ull << 10) #define BO_USE_PROTECTED (1ull << 11) #define BO_USE_HW_VIDEO_ENCODER (1ull << 12) -#define BO_USE_HW_CAMERA_WRITE (1ull << 13) -#define BO_USE_HW_CAMERA_READ (1ull << 14) -#define BO_USE_HW_CAMERA_ZSL (1ull << 15) +#define BO_USE_CAMERA_WRITE (1ull << 13) +#define BO_USE_CAMERA_READ (1ull << 14) #define BO_USE_RENDERSCRIPT (1ull << 16) #define BO_USE_TEXTURE (1ull << 17) +/* Read-Write permissions for drv_bo_map() flags */ +#define BO_TRANSFER_NONE 0 +#define BO_TRANSFER_READ (1 << 0) +#define BO_TRANSFER_WRITE (1 << 1) +#define BO_TRANSFER_READ_WRITE (BO_TRANSFER_READ | BO_TRANSFER_WRITE) + /* This is our extension to <drm_fourcc.h>. We need to make sure we don't step * on the namespace of already defined formats, which can be done by using invalid * fourcc codes. @@ -71,6 +76,7 @@ struct drv_import_fd_data { uint32_t width; uint32_t height; uint32_t format; + uint64_t flags; }; struct map_info { @@ -91,7 +97,8 @@ const char *drv_get_name(struct driver *drv); struct combination *drv_get_combination(struct driver *drv, uint32_t format, uint64_t usage); -struct bo *drv_bo_new(struct driver *drv, uint32_t width, uint32_t height, uint32_t format); +struct bo *drv_bo_new(struct driver *drv, uint32_t width, uint32_t height, uint32_t format, + uint64_t flags); struct bo *drv_bo_create(struct driver *drv, uint32_t width, uint32_t height, uint32_t format, uint64_t flags); @@ -132,7 +139,7 @@ uint32_t drv_bo_get_format(struct bo *bo); uint32_t drv_bo_get_stride_in_pixels(struct bo *bo); -uint32_t drv_resolve_format(struct driver *drv, uint32_t format); +uint32_t drv_resolve_format(struct driver *drv, uint32_t format, uint64_t usage); size_t drv_num_planes_from_format(uint32_t format); diff --git a/chromium/third_party/minigbm/src/drv_priv.h b/chromium/third_party/minigbm/src/drv_priv.h index df5c8e97b26..5547b787e91 100644 --- a/chromium/third_party/minigbm/src/drv_priv.h +++ b/chromium/third_party/minigbm/src/drv_priv.h @@ -26,6 +26,7 @@ struct bo { uint32_t sizes[DRV_MAX_PLANES]; uint32_t strides[DRV_MAX_PLANES]; uint64_t format_modifiers[DRV_MAX_PLANES]; + uint64_t flags; size_t total_size; void *priv; }; @@ -73,19 +74,20 @@ struct backend { uint32_t format, const uint64_t *modifiers, uint32_t count); int (*bo_destroy)(struct bo *bo); int (*bo_import)(struct bo *bo, struct drv_import_fd_data *data); - void *(*bo_map)(struct bo *bo, struct map_info *data, size_t plane); + void *(*bo_map)(struct bo *bo, struct map_info *data, size_t plane, int prot); int (*bo_unmap)(struct bo *bo, struct map_info *data); - uint32_t (*resolve_format)(uint32_t format); + uint32_t (*resolve_format)(uint32_t format, uint64_t usage); struct combinations combos; }; // clang-format off -#define BO_USE_RENDER_MASK BO_USE_LINEAR | BO_USE_RENDERING | BO_USE_SW_READ_OFTEN | \ - BO_USE_SW_WRITE_OFTEN | BO_USE_SW_READ_RARELY | \ +#define BO_USE_RENDER_MASK BO_USE_LINEAR | BO_USE_RENDERING | BO_USE_RENDERSCRIPT | \ + BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN | BO_USE_SW_READ_RARELY | \ BO_USE_SW_WRITE_RARELY | BO_USE_TEXTURE -#define BO_USE_TEXTURE_MASK BO_USE_LINEAR | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN | \ - BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY | BO_USE_TEXTURE +#define BO_USE_TEXTURE_MASK BO_USE_LINEAR | BO_USE_RENDERSCRIPT | BO_USE_SW_READ_OFTEN | \ + BO_USE_SW_WRITE_OFTEN | BO_USE_SW_READ_RARELY | \ + BO_USE_SW_WRITE_RARELY | BO_USE_TEXTURE #define LINEAR_METADATA (struct format_metadata) { 0, 1, DRM_FORMAT_MOD_NONE } // clang-format on diff --git a/chromium/third_party/minigbm/src/gbm.c b/chromium/third_party/minigbm/src/gbm.c index ab576cf926d..37fb1d914c7 100644 --- a/chromium/third_party/minigbm/src/gbm.c +++ b/chromium/third_party/minigbm/src/gbm.c @@ -233,7 +233,10 @@ PUBLIC void *gbm_bo_map(struct gbm_bo *bo, uint32_t x, uint32_t y, uint32_t widt return NULL; *stride = gbm_bo_get_plane_stride(bo, plane); - return drv_bo_map(bo->bo, x, y, width, height, 0, (struct map_info **)map_data, plane); + uint32_t drv_flags = flags & GBM_BO_TRANSFER_READ ? BO_TRANSFER_READ : BO_TRANSFER_NONE; + drv_flags |= flags & GBM_BO_TRANSFER_WRITE ? BO_TRANSFER_WRITE : BO_TRANSFER_NONE; + return drv_bo_map(bo->bo, x, y, width, height, drv_flags, (struct map_info **)map_data, + plane); } PUBLIC void gbm_bo_unmap(struct gbm_bo *bo, void *map_data) diff --git a/chromium/third_party/minigbm/src/gbm.h b/chromium/third_party/minigbm/src/gbm.h index 312b09892dc..5ec13bc003d 100644 --- a/chromium/third_party/minigbm/src/gbm.h +++ b/chromium/third_party/minigbm/src/gbm.h @@ -243,6 +243,14 @@ enum gbm_bo_flags { * The buffer will be used as a texture that will be sampled from. */ GBM_BO_USE_TEXTURING = (1 << 5), + /** + * The buffer will be written to by a camera subsystem. + */ + GBM_BO_USE_CAMERA_WRITE = (1 << 6), + /** + * The buffer will be read from by a camera subsystem. + */ + GBM_BO_USE_CAMERA_READ = (1 << 7), }; int diff --git a/chromium/third_party/minigbm/src/gbm_helpers.c b/chromium/third_party/minigbm/src/gbm_helpers.c index 2b9ce23e6a5..529d7fe73b0 100644 --- a/chromium/third_party/minigbm/src/gbm_helpers.c +++ b/chromium/third_party/minigbm/src/gbm_helpers.c @@ -26,6 +26,10 @@ uint64_t gbm_convert_flags(uint32_t flags) usage |= BO_USE_TEXTURE; if (flags & GBM_BO_USE_LINEAR) usage |= BO_USE_LINEAR; + if (flags & GBM_BO_USE_CAMERA_WRITE) + usage |= BO_USE_CAMERA_WRITE; + if (flags & GBM_BO_USE_CAMERA_READ) + usage |= BO_USE_CAMERA_READ; return usage; } diff --git a/chromium/third_party/minigbm/src/helpers.c b/chromium/third_party/minigbm/src/helpers.c index 806c152ee6f..238563de923 100644 --- a/chromium/third_party/minigbm/src/helpers.c +++ b/chromium/third_party/minigbm/src/helpers.c @@ -147,7 +147,7 @@ int drv_bo_from_format(struct bo *bo, uint32_t stride, uint32_t aligned_height, * - the chroma stride is 16 bytes aligned, i.e., the luma's strides * is 32 bytes aligned. */ - if (bo->format == DRM_FORMAT_YVU420_ANDROID) { + if (format == DRM_FORMAT_YVU420_ANDROID) { assert(aligned_height == bo->height); assert(stride == ALIGN(stride, 32)); } @@ -291,7 +291,7 @@ int drv_prime_bo_import(struct bo *bo, struct drv_import_fd_data *data) return 0; } -void *drv_dumb_bo_map(struct bo *bo, struct map_info *data, size_t plane) +void *drv_dumb_bo_map(struct bo *bo, struct map_info *data, size_t plane, int prot) { int ret; size_t i; @@ -310,8 +310,7 @@ void *drv_dumb_bo_map(struct bo *bo, struct map_info *data, size_t plane) if (bo->handles[i].u32 == bo->handles[plane].u32) data->length += bo->sizes[i]; - return mmap(0, data->length, PROT_READ | PROT_WRITE, MAP_SHARED, bo->drv->fd, - map_dumb.offset); + return mmap(0, data->length, prot, MAP_SHARED, bo->drv->fd, map_dumb.offset); } uintptr_t drv_get_reference_count(struct driver *drv, struct bo *bo, size_t plane) diff --git a/chromium/third_party/minigbm/src/helpers.h b/chromium/third_party/minigbm/src/helpers.h index b42a3c25111..dc1a7c06233 100644 --- a/chromium/third_party/minigbm/src/helpers.h +++ b/chromium/third_party/minigbm/src/helpers.h @@ -16,7 +16,7 @@ int drv_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t int drv_dumb_bo_destroy(struct bo *bo); int drv_gem_bo_destroy(struct bo *bo); int drv_prime_bo_import(struct bo *bo, struct drv_import_fd_data *data); -void *drv_dumb_bo_map(struct bo *bo, struct map_info *data, size_t plane); +void *drv_dumb_bo_map(struct bo *bo, struct map_info *data, size_t plane, int prot); uintptr_t drv_get_reference_count(struct driver *drv, struct bo *bo, size_t plane); void drv_increment_reference_count(struct driver *drv, struct bo *bo, size_t plane); void drv_decrement_reference_count(struct driver *drv, struct bo *bo, size_t plane); diff --git a/chromium/third_party/minigbm/src/i915.c b/chromium/third_party/minigbm/src/i915.c index 59995b26767..fe162f16d50 100644 --- a/chromium/third_party/minigbm/src/i915.c +++ b/chromium/third_party/minigbm/src/i915.c @@ -59,17 +59,22 @@ static int i915_add_kms_item(struct driver *drv, const struct kms_item *item) */ for (i = 0; i < drv->backend->combos.size; i++) { combo = &drv->backend->combos.data[i]; - if (combo->format == item->format) { - if ((combo->metadata.tiling == I915_TILING_Y && - item->modifier == I915_FORMAT_MOD_Y_TILED) || - (combo->metadata.tiling == I915_TILING_X && - item->modifier == I915_FORMAT_MOD_X_TILED)) { - combo->metadata.modifier = item->modifier; - combo->usage |= item->usage; - } else if (combo->metadata.tiling != I915_TILING_Y) { - combo->usage |= item->usage; - } + if (combo->format != item->format) + continue; + + if (item->modifier == DRM_FORMAT_MOD_NONE && + combo->metadata.tiling == I915_TILING_X) { + /* + * FIXME: drv_query_kms() does not report the available modifiers + * yet, but we know that all hardware can scanout from X-tiled + * buffers, so let's add this to our combinations, except for + * cursor, which must not be tiled. + */ + combo->usage |= item->usage & ~BO_USE_CURSOR; } + + if (combo->metadata.modifier == item->modifier) + combo->usage |= item->usage; } return 0; @@ -109,16 +114,29 @@ static int i915_add_combinations(struct driver *drv) drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT); drv_modify_combination(drv, DRM_FORMAT_ARGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT); + /* IPU3 camera ISP supports only NV12 output. */ + drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata, + BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE); + /* + * R8 format is used for Android's HAL_PIXEL_FORMAT_BLOB and is used for JPEG snapshots + * from camera. + */ + drv_modify_combination(drv, DRM_FORMAT_R8, &metadata, + BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE); + + render_flags &= ~BO_USE_RENDERSCRIPT; render_flags &= ~BO_USE_SW_WRITE_OFTEN; render_flags &= ~BO_USE_SW_READ_OFTEN; render_flags &= ~BO_USE_LINEAR; + texture_flags &= ~BO_USE_RENDERSCRIPT; texture_flags &= ~BO_USE_SW_WRITE_OFTEN; texture_flags &= ~BO_USE_SW_READ_OFTEN; texture_flags &= ~BO_USE_LINEAR; metadata.tiling = I915_TILING_X; metadata.priority = 2; + metadata.modifier = I915_FORMAT_MOD_X_TILED; ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), &metadata, render_flags); @@ -133,6 +151,7 @@ static int i915_add_combinations(struct driver *drv) metadata.tiling = I915_TILING_Y; metadata.priority = 3; + metadata.modifier = I915_FORMAT_MOD_Y_TILED; ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), &metadata, render_flags); @@ -190,6 +209,21 @@ static int i915_align_dimensions(struct bo *bo, uint32_t tiling, uint32_t *strid break; } + /* + * The alignment calculated above is based on the full size luma plane and to have chroma + * planes properly aligned with subsampled formats, we need to multiply luma alignment by + * subsampling factor. + */ + switch (bo->format) { + case DRM_FORMAT_YVU420_ANDROID: + case DRM_FORMAT_YVU420: + horizontal_alignment *= 2; + /* Fall through */ + case DRM_FORMAT_NV12: + vertical_alignment *= 2; + break; + } + *aligned_height = ALIGN(bo->height, vertical_alignment); if (i915->gen > 3) { *stride = ALIGN(*stride, horizontal_alignment); @@ -264,16 +298,13 @@ static int i915_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32 uint32_t stride; struct drm_i915_gem_create gem_create; struct drm_i915_gem_set_tiling gem_set_tiling; + struct combination *combo; - if (flags & (BO_USE_CURSOR | BO_USE_LINEAR | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN)) - bo->tiling = I915_TILING_NONE; - else if (flags & BO_USE_SCANOUT) - bo->tiling = I915_TILING_X; - else - bo->tiling = I915_TILING_Y; + combo = drv_get_combination(bo->drv, format, flags); + if (!combo) + return -EINVAL; - if (format == DRM_FORMAT_YVU420 || format == DRM_FORMAT_YVU420_ANDROID) - bo->tiling = I915_TILING_NONE; + bo->tiling = combo->metadata.tiling; stride = drv_stride_from_format(format, width, 0); @@ -282,19 +313,42 @@ static int i915_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32 return ret; /* - * Align the Y plane to 128 bytes so the chroma planes would be aligned - * to 64 byte boundaries. This is an Intel HW requirement. + * HAL_PIXEL_FORMAT_YV12 requires the buffer height not be aligned, but we need to keep + * total size as with aligned height to ensure enough padding space after each plane to + * satisfy GPU alignment requirements. + * + * We do it by first calling drv_bo_from_format() with aligned height and + * DRM_FORMAT_YVU420, which allows height alignment, saving the total size it calculates + * and then calling it again with requested parameters. + * + * This relies on the fact that i965 driver uses separate surfaces for each plane and + * contents of padding bytes is not affected, as it is only used to satisfy GPU cache + * requests. + * + * This is enforced by Mesa in src/intel/isl/isl_gen8.c, inside + * isl_gen8_choose_image_alignment_el(), which is used for GEN9 and GEN8. */ - if (format == DRM_FORMAT_YVU420) - stride = ALIGN(stride, 128); + if (format == DRM_FORMAT_YVU420_ANDROID) { + uint32_t unaligned_height = bo->height; + size_t total_size; + + drv_bo_from_format(bo, stride, height, DRM_FORMAT_YVU420); + total_size = bo->total_size; + drv_bo_from_format(bo, stride, unaligned_height, format); + bo->total_size = total_size; + } else { + drv_bo_from_format(bo, stride, height, format); + } /* - * HAL_PIXEL_FORMAT_YV12 requires that the buffer's height not be aligned. + * Quoting Mesa ISL library: + * + * - For linear surfaces, additional padding of 64 bytes is required at + * the bottom of the surface. This is in addition to the padding + * required above. */ - if (format == DRM_FORMAT_YVU420_ANDROID) - height = bo->height; - - drv_bo_from_format(bo, stride, height, format); + if (bo->tiling == I915_TILING_NONE) + bo->total_size += 64; memset(&gem_create, 0, sizeof(gem_create)); gem_create.size = bo->total_size; @@ -349,6 +403,7 @@ static int i915_bo_import(struct bo *bo, struct drv_import_fd_data *data) ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_GET_TILING, &gem_get_tiling); if (ret) { + drv_gem_bo_destroy(bo); fprintf(stderr, "drv: DRM_IOCTL_I915_GEM_GET_TILING failed."); return ret; } @@ -357,7 +412,7 @@ static int i915_bo_import(struct bo *bo, struct drv_import_fd_data *data) return 0; } -static void *i915_bo_map(struct bo *bo, struct map_info *data, size_t plane) +static void *i915_bo_map(struct bo *bo, struct map_info *data, size_t plane, int prot) { int ret; void *addr; @@ -395,9 +450,7 @@ static void *i915_bo_map(struct bo *bo, struct map_info *data, size_t plane) return MAP_FAILED; } - addr = mmap(0, bo->total_size, PROT_READ | PROT_WRITE, MAP_SHARED, bo->drv->fd, - gem_map.offset); - + addr = mmap(0, bo->total_size, prot, MAP_SHARED, bo->drv->fd, gem_map.offset); set_domain.read_domains = I915_GEM_DOMAIN_GTT; set_domain.write_domain = I915_GEM_DOMAIN_GTT; } @@ -426,13 +479,19 @@ static int i915_bo_unmap(struct bo *bo, struct map_info *data) return munmap(data->addr, data->length); } -static uint32_t i915_resolve_format(uint32_t format) +static uint32_t i915_resolve_format(uint32_t format, uint64_t usage) { switch (format) { case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED: + /* KBL camera subsystem requires NV12. */ + if (usage & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE)) + return DRM_FORMAT_NV12; /*HACK: See b/28671744 */ return DRM_FORMAT_XBGR8888; case DRM_FORMAT_FLEX_YCbCr_420_888: + /* KBL camera subsystem requires NV12. */ + if (usage & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE)) + return DRM_FORMAT_NV12; return DRM_FORMAT_YVU420; default: return format; diff --git a/chromium/third_party/minigbm/src/mediatek.c b/chromium/third_party/minigbm/src/mediatek.c index d2e9f53b567..a4879d9d623 100644 --- a/chromium/third_party/minigbm/src/mediatek.c +++ b/chromium/third_party/minigbm/src/mediatek.c @@ -18,6 +18,11 @@ #include "helpers.h" #include "util.h" +struct mediatek_private_map_data { + void *cached_addr; + void *gem_addr; +}; + static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888, DRM_FORMAT_XRGB8888 }; @@ -73,10 +78,11 @@ static int mediatek_bo_create(struct bo *bo, uint32_t width, uint32_t height, ui return 0; } -static void *mediatek_bo_map(struct bo *bo, struct map_info *data, size_t plane) +static void *mediatek_bo_map(struct bo *bo, struct map_info *data, size_t plane, int prot) { int ret; struct drm_mtk_gem_map_off gem_map; + struct mediatek_private_map_data *priv; memset(&gem_map, 0, sizeof(gem_map)); gem_map.handle = bo->handles[0].u32; @@ -87,13 +93,37 @@ static void *mediatek_bo_map(struct bo *bo, struct map_info *data, size_t plane) return MAP_FAILED; } + void *addr = mmap(0, bo->total_size, prot, MAP_SHARED, bo->drv->fd, gem_map.offset); + data->length = bo->total_size; - return mmap(0, bo->total_size, PROT_READ | PROT_WRITE, MAP_SHARED, bo->drv->fd, - gem_map.offset); + if (bo->flags & BO_USE_RENDERSCRIPT) { + priv = calloc(1, sizeof(*priv)); + priv->cached_addr = calloc(1, bo->total_size); + priv->gem_addr = addr; + memcpy(priv->cached_addr, priv->gem_addr, bo->total_size); + data->priv = priv; + addr = priv->cached_addr; + } + + return addr; +} + +static int mediatek_bo_unmap(struct bo *bo, struct map_info *data) +{ + if (data->priv) { + struct mediatek_private_map_data *priv = data->priv; + memcpy(priv->gem_addr, priv->cached_addr, bo->total_size); + data->addr = priv->gem_addr; + free(priv->cached_addr); + free(priv); + data->priv = NULL; + } + + return munmap(data->addr, data->length); } -static uint32_t mediatek_resolve_format(uint32_t format) +static uint32_t mediatek_resolve_format(uint32_t format, uint64_t usage) { switch (format) { case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED: @@ -113,6 +143,7 @@ struct backend backend_mediatek = { .bo_destroy = drv_gem_bo_destroy, .bo_import = drv_prime_bo_import, .bo_map = mediatek_bo_map, + .bo_unmap = mediatek_bo_unmap, .resolve_format = mediatek_resolve_format, }; diff --git a/chromium/third_party/minigbm/src/radeon.c b/chromium/third_party/minigbm/src/radeon.c new file mode 100644 index 00000000000..baf42ed994f --- /dev/null +++ b/chromium/third_party/minigbm/src/radeon.c @@ -0,0 +1,31 @@ +/* + * Copyright 2017 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "drv_priv.h" +#include "helpers.h" +#include "util.h" + +static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 }; + +static int radeon_init(struct driver *drv) +{ + int ret; + ret = drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), + &LINEAR_METADATA, BO_USE_RENDER_MASK); + if (ret) + return ret; + + return drv_modify_linear_combinations(drv); +} + +struct backend backend_radeon = { + .name = "radeon", + .init = radeon_init, + .bo_create = drv_dumb_bo_create, + .bo_destroy = drv_dumb_bo_destroy, + .bo_import = drv_prime_bo_import, + .bo_map = drv_dumb_bo_map, +}; diff --git a/chromium/third_party/minigbm/src/rockchip.c b/chromium/third_party/minigbm/src/rockchip.c index 50ea4ef7640..fbc9ed5c0de 100644 --- a/chromium/third_party/minigbm/src/rockchip.c +++ b/chromium/third_party/minigbm/src/rockchip.c @@ -18,6 +18,11 @@ #include "helpers.h" #include "util.h" +struct rockchip_private_map_data { + void *cached_addr; + void *gem_addr; +}; + static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888, DRM_FORMAT_XRGB8888 }; @@ -225,10 +230,11 @@ static int rockchip_bo_create(struct bo *bo, uint32_t width, uint32_t height, ui ARRAY_SIZE(modifiers)); } -static void *rockchip_bo_map(struct bo *bo, struct map_info *data, size_t plane) +static void *rockchip_bo_map(struct bo *bo, struct map_info *data, size_t plane, int prot) { int ret; struct drm_rockchip_gem_map_off gem_map; + struct rockchip_private_map_data *priv; /* We can only map buffers created with SW access flags, which should * have no modifiers (ie, not AFBC). */ @@ -244,13 +250,37 @@ static void *rockchip_bo_map(struct bo *bo, struct map_info *data, size_t plane) return MAP_FAILED; } + void *addr = mmap(0, bo->total_size, prot, MAP_SHARED, bo->drv->fd, gem_map.offset); + data->length = bo->total_size; - return mmap(0, bo->total_size, PROT_READ | PROT_WRITE, MAP_SHARED, bo->drv->fd, - gem_map.offset); + if (bo->flags & BO_USE_RENDERSCRIPT) { + priv = calloc(1, sizeof(*priv)); + priv->cached_addr = calloc(1, bo->total_size); + priv->gem_addr = addr; + memcpy(priv->cached_addr, priv->gem_addr, bo->total_size); + data->priv = priv; + addr = priv->cached_addr; + } + + return addr; +} + +static int rockchip_bo_unmap(struct bo *bo, struct map_info *data) +{ + if (data->priv) { + struct rockchip_private_map_data *priv = data->priv; + memcpy(priv->gem_addr, priv->cached_addr, bo->total_size); + data->addr = priv->gem_addr; + free(priv->cached_addr); + free(priv); + data->priv = NULL; + } + + return munmap(data->addr, data->length); } -static uint32_t rockchip_resolve_format(uint32_t format) +static uint32_t rockchip_resolve_format(uint32_t format, uint64_t usage) { switch (format) { case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED: @@ -271,6 +301,7 @@ struct backend backend_rockchip = { .bo_destroy = drv_gem_bo_destroy, .bo_import = drv_prime_bo_import, .bo_map = rockchip_bo_map, + .bo_unmap = rockchip_bo_unmap, .resolve_format = rockchip_resolve_format, }; diff --git a/chromium/third_party/minigbm/src/tegra.c b/chromium/third_party/minigbm/src/tegra.c index 09ca8b2372e..7ddeb96873c 100644 --- a/chromium/third_party/minigbm/src/tegra.c +++ b/chromium/third_party/minigbm/src/tegra.c @@ -44,6 +44,7 @@ enum tegra_map_type { struct tegra_private_map_data { void *tiled; void *untiled; + int prot; }; static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 }; @@ -102,7 +103,7 @@ static void compute_layout_linear(int width, int height, int format, uint32_t *s static void transfer_tile(struct bo *bo, uint8_t *tiled, uint8_t *untiled, enum tegra_map_type type, uint32_t bytes_per_pixel, uint32_t gob_top, uint32_t gob_left, - uint32_t gob_size_pixels) + uint32_t gob_size_pixels, uint8_t *tiled_last) { uint8_t *tmp; uint32_t x, y, k; @@ -115,7 +116,15 @@ static void transfer_tile(struct bo *bo, uint8_t *tiled, uint8_t *untiled, enum x = gob_left + (((k >> 3) & 8) | ((k >> 1) & 4) | (k & 3)); y = gob_top + ((k >> 7 << 3) | ((k >> 3) & 6) | ((k >> 2) & 1)); - tmp = untiled + (y * bo->strides[0]) + (x * bytes_per_pixel); + if (tiled >= tiled_last) + return; + + if (x >= bo->width || y >= bo->height) { + tiled += bytes_per_pixel; + continue; + } + + tmp = untiled + y * bo->strides[0] + x * bytes_per_pixel; if (type == TEGRA_READ_TILED_BUFFER) memcpy(tmp, tiled, bytes_per_pixel); @@ -133,7 +142,7 @@ static void transfer_tiled_memory(struct bo *bo, uint8_t *tiled, uint8_t *untile uint32_t gob_width, gob_height, gob_size_bytes, gob_size_pixels, gob_count_x, gob_count_y, gob_top, gob_left; uint32_t i, j, offset; - uint8_t *tmp; + uint8_t *tmp, *tiled_last; uint32_t bytes_per_pixel = drv_stride_from_format(bo->format, 1, 0); /* @@ -152,6 +161,8 @@ static void transfer_tiled_memory(struct bo *bo, uint8_t *tiled, uint8_t *untile gob_count_x = DIV_ROUND_UP(bo->strides[0], NV_BLOCKLINEAR_GOB_WIDTH); gob_count_y = DIV_ROUND_UP(bo->height, gob_height); + tiled_last = tiled + bo->total_size; + offset = 0; for (j = 0; j < gob_count_y; j++) { gob_top = j * gob_height; @@ -160,7 +171,7 @@ static void transfer_tiled_memory(struct bo *bo, uint8_t *tiled, uint8_t *untile gob_left = i * gob_width; transfer_tile(bo, tmp, untiled, type, bytes_per_pixel, gob_top, gob_left, - gob_size_pixels); + gob_size_pixels, tiled_last); offset += gob_size_bytes; } @@ -254,7 +265,7 @@ static int tegra_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint3 return 0; } -static void *tegra_bo_map(struct bo *bo, struct map_info *data, size_t plane) +static void *tegra_bo_map(struct bo *bo, struct map_info *data, size_t plane, int prot) { int ret; struct drm_tegra_gem_mmap gem_map; @@ -269,14 +280,13 @@ static void *tegra_bo_map(struct bo *bo, struct map_info *data, size_t plane) return MAP_FAILED; } - void *addr = mmap(0, bo->total_size, PROT_READ | PROT_WRITE, MAP_SHARED, bo->drv->fd, - gem_map.offset); - + void *addr = mmap(0, bo->total_size, prot, MAP_SHARED, bo->drv->fd, gem_map.offset); data->length = bo->total_size; if ((bo->tiling & 0xFF) == NV_MEM_KIND_C32_2CRA && addr != MAP_FAILED) { priv = calloc(1, sizeof(*priv)); priv->untiled = calloc(1, bo->total_size); priv->tiled = addr; + priv->prot = prot; data->priv = priv; transfer_tiled_memory(bo, priv->tiled, priv->untiled, TEGRA_READ_TILED_BUFFER); addr = priv->untiled; @@ -289,7 +299,9 @@ static int tegra_bo_unmap(struct bo *bo, struct map_info *data) { if (data->priv) { struct tegra_private_map_data *priv = data->priv; - transfer_tiled_memory(bo, priv->tiled, priv->untiled, TEGRA_WRITE_TILED_BUFFER); + if (priv->prot & PROT_WRITE) + transfer_tiled_memory(bo, priv->tiled, priv->untiled, + TEGRA_WRITE_TILED_BUFFER); data->addr = priv->tiled; free(priv->untiled); free(priv); diff --git a/chromium/third_party/minigbm/src/vc4.c b/chromium/third_party/minigbm/src/vc4.c index 99896b9b772..c797bd9529c 100644 --- a/chromium/third_party/minigbm/src/vc4.c +++ b/chromium/third_party/minigbm/src/vc4.c @@ -62,7 +62,7 @@ static int vc4_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_ return 0; } -static void *vc4_bo_map(struct bo *bo, struct map_info *data, size_t plane) +static void *vc4_bo_map(struct bo *bo, struct map_info *data, size_t plane, int prot) { int ret; struct drm_vc4_mmap_bo bo_map; @@ -77,9 +77,7 @@ static void *vc4_bo_map(struct bo *bo, struct map_info *data, size_t plane) } data->length = bo->total_size; - - return mmap(0, bo->total_size, PROT_READ | PROT_WRITE, MAP_SHARED, bo->drv->fd, - bo_map.offset); + return mmap(0, bo->total_size, prot, MAP_SHARED, bo->drv->fd, bo_map.offset); } struct backend backend_vc4 = { diff --git a/chromium/third_party/minigbm/src/vgem.c b/chromium/third_party/minigbm/src/vgem.c index 9bf5b878571..4e6eefb7375 100644 --- a/chromium/third_party/minigbm/src/vgem.c +++ b/chromium/third_party/minigbm/src/vgem.c @@ -47,7 +47,7 @@ static int vgem_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32 return drv_dumb_bo_create(bo, width, height, format, flags); } -static uint32_t vgem_resolve_format(uint32_t format) +static uint32_t vgem_resolve_format(uint32_t format, uint64_t usage) { switch (format) { case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED: diff --git a/chromium/third_party/minigbm/src/virtio_gpu.c b/chromium/third_party/minigbm/src/virtio_gpu.c index ab1d8f10ec4..fe580cd15b6 100644 --- a/chromium/third_party/minigbm/src/virtio_gpu.c +++ b/chromium/third_party/minigbm/src/virtio_gpu.c @@ -47,7 +47,7 @@ static int virtio_gpu_bo_create(struct bo *bo, uint32_t width, uint32_t height, return drv_dumb_bo_create(bo, width, height, format, flags); } -static uint32_t virtio_gpu_resolve_format(uint32_t format) +static uint32_t virtio_gpu_resolve_format(uint32_t format, uint64_t usage) { switch (format) { case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED: |