summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGurchetan Singh <gurchetansingh@chromium.org>2017-11-06 11:07:52 -0800
committerchrome-bot <chrome-bot@chromium.org>2017-11-16 13:52:02 -0800
commit1ef809ecd434bfc0fd1d669ba925d58b1255d163 (patch)
tree2021d33b377ae8aec16d1eee63854ab24f24954b
parentee43c301c21976fb82538261c4e4288ffc754777 (diff)
minigbm: plumb buffer access region
This will allow drivers to tile or detile only the regions requested by the user. Note that the gralloc spec states that: "This address will represent the top-left corner of the entire buffer, even if accessRegion does not begin at the top-left corner." (see hardware/interfaces/graphics/mapper/2.0/IMapper.hal in AOSP) Also, the gralloc API makes it difficult to maintain two mappings of the same buffer. For example, say you have two access regions: module->lock(mod, handle1, 0, 0, 5, 5, &addr); module->lock(mod, handle1, 5, 5, 10, 10, &addr); module->unlock(mod, handle1); // which access region should be unlocked? In practice, this scenario never happens on Android. It's not exactly clear what gbm should return. Let's just return the top left of the access region because that's what we where doing before. BUG=chromium:764871 TEST=gbmtest, mmap_test -g, the following CTS tests: android.view.cts.SurfaceViewSyncTests android.media.cts.EncodeDecodeTest android.video.cts.VideoEncoderDecoderTest Change-Id: I7ca0713871e03928b1d4402aa161588990c7e775 Reviewed-on: https://chromium-review.googlesource.com/758147 Commit-Ready: Gurchetan Singh <gurchetansingh@chromium.org> Tested-by: Gurchetan Singh <gurchetansingh@chromium.org> Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
-rw-r--r--cros_gralloc/cros_gralloc_buffer.cc6
-rw-r--r--cros_gralloc/cros_gralloc_buffer.h3
-rw-r--r--cros_gralloc/cros_gralloc_driver.cc5
-rw-r--r--cros_gralloc/cros_gralloc_driver.h4
-rw-r--r--cros_gralloc/gralloc0/gralloc0.cc22
-rw-r--r--drv.c48
-rw-r--r--drv.h15
-rw-r--r--gbm.c14
-rw-r--r--helpers.h1
9 files changed, 89 insertions, 29 deletions
diff --git a/cros_gralloc/cros_gralloc_buffer.cc b/cros_gralloc/cros_gralloc_buffer.cc
index c84e21a..7757069 100644
--- a/cros_gralloc/cros_gralloc_buffer.cc
+++ b/cros_gralloc/cros_gralloc_buffer.cc
@@ -44,7 +44,8 @@ int32_t cros_gralloc_buffer::decrease_refcount()
return --refcount_;
}
-int32_t cros_gralloc_buffer::lock(uint32_t map_flags, uint8_t *addr[DRV_MAX_PLANES])
+int32_t cros_gralloc_buffer::lock(const struct rectangle *rect, uint32_t map_flags,
+ uint8_t *addr[DRV_MAX_PLANES])
{
void *vaddr = nullptr;
@@ -64,8 +65,7 @@ int32_t cros_gralloc_buffer::lock(uint32_t map_flags, uint8_t *addr[DRV_MAX_PLAN
drv_bo_invalidate(bo_, lock_data_[0]);
vaddr = lock_data_[0]->vma->addr;
} else {
- vaddr = drv_bo_map(bo_, 0, 0, drv_bo_get_width(bo_), drv_bo_get_height(bo_),
- map_flags, &lock_data_[0], 0);
+ vaddr = drv_bo_map(bo_, rect, map_flags, &lock_data_[0], 0);
}
if (vaddr == MAP_FAILED) {
diff --git a/cros_gralloc/cros_gralloc_buffer.h b/cros_gralloc/cros_gralloc_buffer.h
index 93ec37f..e6aec91 100644
--- a/cros_gralloc/cros_gralloc_buffer.h
+++ b/cros_gralloc/cros_gralloc_buffer.h
@@ -23,7 +23,8 @@ class cros_gralloc_buffer
int32_t increase_refcount();
int32_t decrease_refcount();
- int32_t lock(uint32_t map_flags, uint8_t *addr[DRV_MAX_PLANES]);
+ int32_t lock(const struct rectangle *rect, uint32_t map_flags,
+ uint8_t *addr[DRV_MAX_PLANES]);
int32_t unlock();
private:
diff --git a/cros_gralloc/cros_gralloc_driver.cc b/cros_gralloc/cros_gralloc_driver.cc
index 3a0b013..fec4aba 100644
--- a/cros_gralloc/cros_gralloc_driver.cc
+++ b/cros_gralloc/cros_gralloc_driver.cc
@@ -235,7 +235,8 @@ int32_t cros_gralloc_driver::release(buffer_handle_t handle)
return 0;
}
-int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence, uint32_t map_flags,
+int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence,
+ const struct rectangle *rect, uint32_t map_flags,
uint8_t *addr[DRV_MAX_PLANES])
{
int32_t ret = cros_gralloc_sync_wait(acquire_fence);
@@ -255,7 +256,7 @@ int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence,
return -EINVAL;
}
- return buffer->lock(map_flags, addr);
+ return buffer->lock(rect, map_flags, addr);
}
int32_t cros_gralloc_driver::unlock(buffer_handle_t handle, int32_t *release_fence)
diff --git a/cros_gralloc/cros_gralloc_driver.h b/cros_gralloc/cros_gralloc_driver.h
index dea2ac0..45782c9 100644
--- a/cros_gralloc/cros_gralloc_driver.h
+++ b/cros_gralloc/cros_gralloc_driver.h
@@ -26,8 +26,8 @@ class cros_gralloc_driver
int32_t retain(buffer_handle_t handle);
int32_t release(buffer_handle_t handle);
- int32_t lock(buffer_handle_t handle, int32_t acquire_fence, uint32_t map_flags,
- uint8_t *addr[DRV_MAX_PLANES]);
+ int32_t lock(buffer_handle_t handle, int32_t acquire_fence, const struct rectangle *rect,
+ uint32_t map_flags, uint8_t *addr[DRV_MAX_PLANES]);
int32_t unlock(buffer_handle_t handle, int32_t *release_fence);
int32_t get_backing_store(buffer_handle_t handle, uint64_t *out_store);
diff --git a/cros_gralloc/gralloc0/gralloc0.cc b/cros_gralloc/gralloc0/gralloc0.cc
index ab05376..b055f65 100644
--- a/cros_gralloc/gralloc0/gralloc0.cc
+++ b/cros_gralloc/gralloc0/gralloc0.cc
@@ -297,6 +297,10 @@ static int gralloc0_lock_async(struct gralloc_module_t const *module, buffer_han
uint32_t map_flags;
uint8_t *addr[DRV_MAX_PLANES];
auto mod = (struct gralloc0_module *)module;
+ struct rectangle rect = { .x = static_cast<uint32_t>(l),
+ .y = static_cast<uint32_t>(t),
+ .width = static_cast<uint32_t>(w),
+ .height = static_cast<uint32_t>(h) };
auto hnd = cros_gralloc_convert_handle(handle);
if (!hnd) {
@@ -309,8 +313,13 @@ static int gralloc0_lock_async(struct gralloc_module_t const *module, buffer_han
return -EINVAL;
}
+ assert(l >= 0);
+ assert(t >= 0);
+ assert(w >= 0);
+ assert(h >= 0);
+
map_flags = gralloc0_convert_map_usage(usage);
- ret = mod->driver->lock(handle, fence_fd, map_flags, addr);
+ ret = mod->driver->lock(handle, fence_fd, &rect, map_flags, addr);
*vaddr = addr[0];
return ret;
}
@@ -330,6 +339,10 @@ static int gralloc0_lock_async_ycbcr(struct gralloc_module_t const *module, buff
uint32_t map_flags;
uint8_t *addr[DRV_MAX_PLANES] = { nullptr, nullptr, nullptr, nullptr };
auto mod = (struct gralloc0_module *)module;
+ struct rectangle rect = { .x = static_cast<uint32_t>(l),
+ .y = static_cast<uint32_t>(t),
+ .width = static_cast<uint32_t>(w),
+ .height = static_cast<uint32_t>(h) };
auto hnd = cros_gralloc_convert_handle(handle);
if (!hnd) {
@@ -344,8 +357,13 @@ static int gralloc0_lock_async_ycbcr(struct gralloc_module_t const *module, buff
return -EINVAL;
}
+ assert(l >= 0);
+ assert(t >= 0);
+ assert(w >= 0);
+ assert(h >= 0);
+
map_flags = gralloc0_convert_map_usage(usage);
- ret = mod->driver->lock(handle, fence_fd, map_flags, addr);
+ ret = mod->driver->lock(handle, fence_fd, &rect, map_flags, addr);
if (ret)
return ret;
diff --git a/drv.c b/drv.c
index cd8251f..a1be245 100644
--- a/drv.c
+++ b/drv.c
@@ -382,23 +382,25 @@ destroy_bo:
return NULL;
}
-void *drv_bo_map(struct bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height,
- uint32_t map_flags, struct mapping **map_data, size_t plane)
+void *drv_bo_map(struct bo *bo, const struct rectangle *rect, uint32_t map_flags,
+ struct mapping **map_data, size_t plane)
{
uint32_t i;
uint8_t *addr;
- size_t offset;
struct mapping mapping;
- assert(width > 0);
- assert(height > 0);
- assert(x + width <= drv_bo_get_width(bo));
- assert(y + height <= drv_bo_get_height(bo));
+ assert(rect->width >= 0);
+ assert(rect->height >= 0);
+ assert(rect->x + rect->width <= drv_bo_get_width(bo));
+ assert(rect->y + rect->height <= drv_bo_get_height(bo));
assert(BO_MAP_READ_WRITE & map_flags);
/* No CPU access for protected buffers. */
assert(!(bo->use_flags & BO_USE_PROTECTED));
memset(&mapping, 0, sizeof(mapping));
+ mapping.rect = *rect;
+ mapping.refcount = 1;
+
pthread_mutex_lock(&bo->drv->driver_lock);
for (i = 0; i < drv_array_size(bo->drv->mappings); i++) {
@@ -407,6 +409,21 @@ void *drv_bo_map(struct bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t
prior->vma->map_flags != map_flags)
continue;
+ if (rect->x != prior->rect.x || rect->y != prior->rect.y ||
+ rect->width != prior->rect.width || rect->height != prior->rect.height)
+ continue;
+
+ prior->refcount++;
+ *map_data = prior;
+ goto exact_match;
+ }
+
+ for (i = 0; i < drv_array_size(bo->drv->mappings); i++) {
+ struct mapping *prior = (struct mapping *)drv_array_at_idx(bo->drv->mappings, i);
+ if (prior->vma->handle != bo->handles[plane].u32 ||
+ prior->vma->map_flags != map_flags)
+ continue;
+
prior->vma->refcount++;
mapping.vma = prior->vma;
goto success;
@@ -427,14 +444,12 @@ void *drv_bo_map(struct bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t
mapping.vma->map_flags = map_flags;
success:
- drv_bo_invalidate(bo, &mapping);
*map_data = drv_array_append(bo->drv->mappings, &mapping);
- offset = drv_bo_get_plane_stride(bo, plane) * y;
- offset += drv_stride_from_format(bo->format, x, plane);
- addr = (uint8_t *)mapping.vma->addr;
- addr += drv_bo_get_plane_offset(bo, plane) + offset;
+exact_match:
+ drv_bo_invalidate(bo, *map_data);
+ addr = (uint8_t *)((*map_data)->vma->addr);
+ addr += drv_bo_get_plane_offset(bo, plane);
pthread_mutex_unlock(&bo->drv->driver_lock);
-
return (void *)addr;
}
@@ -447,6 +462,9 @@ int drv_bo_unmap(struct bo *bo, struct mapping *mapping)
pthread_mutex_lock(&bo->drv->driver_lock);
+ if (--mapping->refcount)
+ goto out;
+
if (!--mapping->vma->refcount) {
ret = bo->drv->backend->bo_unmap(bo, mapping->vma);
free(mapping->vma);
@@ -459,8 +477,8 @@ int drv_bo_unmap(struct bo *bo, struct mapping *mapping)
}
}
+out:
pthread_mutex_unlock(&bo->drv->driver_lock);
-
return ret;
}
@@ -470,6 +488,7 @@ int drv_bo_invalidate(struct bo *bo, struct mapping *mapping)
assert(mapping);
assert(mapping->vma);
+ assert(mapping->refcount > 0);
assert(mapping->vma->refcount > 0);
if (bo->drv->backend->bo_invalidate)
@@ -484,6 +503,7 @@ int drv_bo_flush(struct bo *bo, struct mapping *mapping)
assert(mapping);
assert(mapping->vma);
+ assert(mapping->refcount > 0);
assert(mapping->vma->refcount > 0);
assert(!(bo->use_flags & BO_USE_PROTECTED));
diff --git a/drv.h b/drv.h
index bfde327..18653e5 100644
--- a/drv.h
+++ b/drv.h
@@ -87,8 +87,17 @@ struct vma {
void *priv;
};
+struct rectangle {
+ uint32_t x;
+ uint32_t y;
+ uint32_t width;
+ uint32_t height;
+};
+
struct mapping {
struct vma *vma;
+ struct rectangle rect;
+ uint32_t refcount;
};
struct driver *drv_create(int fd);
@@ -114,8 +123,8 @@ void drv_bo_destroy(struct bo *bo);
struct bo *drv_bo_import(struct driver *drv, struct drv_import_fd_data *data);
-void *drv_bo_map(struct bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height,
- uint32_t map_flags, struct mapping **map_data, size_t plane);
+void *drv_bo_map(struct bo *bo, const struct rectangle *rect, uint32_t map_flags,
+ struct mapping **map_data, size_t plane);
int drv_bo_unmap(struct bo *bo, struct mapping *mapping);
@@ -147,6 +156,8 @@ uint32_t drv_bo_get_format(struct bo *bo);
uint32_t drv_bo_get_stride_in_pixels(struct bo *bo);
+uint32_t drv_stride_from_format(uint32_t format, uint32_t width, size_t plane);
+
uint32_t drv_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags);
size_t drv_num_planes_from_format(uint32_t format);
diff --git a/gbm.c b/gbm.c
index 606b195..c67bdcd 100644
--- a/gbm.c
+++ b/gbm.c
@@ -10,6 +10,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/mman.h>
#include <xf86drm.h>
#include "drv.h"
@@ -225,15 +226,24 @@ PUBLIC struct gbm_bo *gbm_bo_import(struct gbm_device *gbm, uint32_t type, void
PUBLIC void *gbm_bo_map(struct gbm_bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height,
uint32_t transfer_flags, uint32_t *stride, void **map_data, size_t plane)
{
+ void *addr;
+ off_t offset;
uint32_t map_flags;
+ struct rectangle rect = { .x = x, .y = y, .width = width, .height = height };
if (!bo || width == 0 || height == 0 || !stride || !map_data)
return NULL;
*stride = gbm_bo_get_plane_stride(bo, plane);
map_flags = (transfer_flags & GBM_BO_TRANSFER_READ) ? BO_MAP_READ : BO_MAP_NONE;
map_flags |= (transfer_flags & GBM_BO_TRANSFER_WRITE) ? BO_MAP_WRITE : BO_MAP_NONE;
- return drv_bo_map(bo->bo, x, y, width, height, map_flags, (struct mapping **)map_data,
- plane);
+
+ addr = drv_bo_map(bo->bo, &rect, map_flags, (struct mapping **)map_data, plane);
+ if (addr == MAP_FAILED)
+ return MAP_FAILED;
+
+ offset = gbm_bo_get_plane_stride(bo, plane) * rect.y;
+ offset += drv_stride_from_format(bo->gbm_format, rect.x, plane);
+ return (void *)((uint8_t *)addr + offset);
}
PUBLIC void gbm_bo_unmap(struct gbm_bo *bo, void *map_data)
diff --git a/helpers.h b/helpers.h
index 9c9dcc6..92a5017 100644
--- a/helpers.h
+++ b/helpers.h
@@ -10,7 +10,6 @@
#include "drv.h"
#include "helpers_array.h"
-uint32_t drv_stride_from_format(uint32_t format, uint32_t width, size_t plane);
uint32_t drv_size_from_format(uint32_t format, uint32_t stride, uint32_t height, size_t plane);
int drv_bo_from_format(struct bo *bo, uint32_t stride, uint32_t aligned_height, uint32_t format);
int drv_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,