174 lines
4.9 KiB
C++
174 lines
4.9 KiB
C++
// Copyright 2021 The ChromiumOS Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "sommelier-mmap.h" // NOLINT(build/include_directory)
|
|
|
|
#include <assert.h>
|
|
#include <unistd.h>
|
|
|
|
#include "../sommelier.h" // NOLINT(build/include_directory)
|
|
#include "../sommelier-tracing.h" // NOLINT(build/include_directory)
|
|
|
|
struct sl_mmap* sl_mmap_create(int fd,
|
|
size_t size,
|
|
size_t bpp,
|
|
size_t num_planes,
|
|
size_t offset0,
|
|
size_t stride0,
|
|
size_t offset1,
|
|
size_t stride1,
|
|
size_t y_ss0,
|
|
size_t y_ss1) {
|
|
TRACE_EVENT("shm", "sl_mmap_create");
|
|
struct sl_mmap* map = new sl_mmap();
|
|
map->refcount = 1;
|
|
map->fd = fd;
|
|
map->size = size;
|
|
map->map_type = SL_MMAP_SHM;
|
|
map->gbm_map_data = NULL;
|
|
map->gbmbo = NULL;
|
|
map->num_planes = num_planes;
|
|
map->bpp = bpp;
|
|
map->offset[0] = offset0;
|
|
map->stride[0] = stride0;
|
|
map->offset[1] = offset1;
|
|
map->stride[1] = stride1;
|
|
map->y_ss[0] = y_ss0;
|
|
map->y_ss[1] = y_ss1;
|
|
map->begin_write = NULL;
|
|
map->end_write = NULL;
|
|
map->buffer_resource = NULL;
|
|
map->addr =
|
|
mmap(NULL, size + offset0, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
|
errno_assert(map->addr != MAP_FAILED);
|
|
|
|
return map;
|
|
}
|
|
|
|
struct sl_mmap* sl_drm_prime_mmap_create(gbm_device* device,
|
|
int fd,
|
|
size_t bpp,
|
|
size_t num_planes,
|
|
size_t stride,
|
|
int32_t width,
|
|
int32_t height,
|
|
uint32_t drm_format) {
|
|
TRACE_EVENT("drm", "sl_drm_mmap_create");
|
|
struct sl_mmap* map = new sl_mmap();
|
|
assert(num_planes == 1);
|
|
|
|
map->refcount = 1;
|
|
map->fd = fd;
|
|
map->num_planes = num_planes;
|
|
map->bpp = bpp;
|
|
map->offset[0] = 0;
|
|
map->stride[0] = stride;
|
|
map->offset[1] = 0;
|
|
map->stride[1] = 0;
|
|
map->y_ss[0] = 1;
|
|
map->y_ss[1] = 1;
|
|
map->begin_write = NULL;
|
|
map->end_write = NULL;
|
|
map->buffer_resource = NULL;
|
|
map->map_type = SL_MMAP_DRM_PRIME;
|
|
map->gbm_map_data = NULL;
|
|
map->addr = NULL;
|
|
map->gbmbo = NULL;
|
|
|
|
// Prefill in the gbm_import_data structure
|
|
map->gbm_import_data.fd = fd;
|
|
map->gbm_import_data.width = width;
|
|
map->gbm_import_data.height = height;
|
|
map->gbm_import_data.stride = stride;
|
|
map->gbm_import_data.format = drm_format;
|
|
|
|
// Save the device as we will need it later
|
|
map->gbm_device_object = device;
|
|
return map;
|
|
}
|
|
|
|
struct sl_mmap* sl_mmap_ref(struct sl_mmap* map) {
|
|
TRACE_EVENT("shm", "sl_mmap_ref");
|
|
map->refcount++;
|
|
return map;
|
|
}
|
|
|
|
bool sl_mmap_begin_access(struct sl_mmap* map) {
|
|
uint32_t ret_stride;
|
|
|
|
// This function is to be used on the DRM PRIME mmap path.
|
|
// It is used to ensure we can actually access the resource
|
|
// when its contents are needed.
|
|
// If we have any other mmap type, we should simply return true
|
|
// under the assumption that they do not need to perform this extra
|
|
// check
|
|
if (map->map_type != SL_MMAP_DRM_PRIME)
|
|
return true;
|
|
|
|
// Attempt to import (and map) the GBM BO
|
|
// If we cannot do so, return false so the upper layers
|
|
// can respond appropriately.
|
|
map->gbmbo = gbm_bo_import(map->gbm_device_object, GBM_BO_IMPORT_FD,
|
|
reinterpret_cast<void*>(&map->gbm_import_data),
|
|
GBM_BO_USE_LINEAR);
|
|
if (!map->gbmbo) {
|
|
return false;
|
|
}
|
|
|
|
map->gbm_map_data = NULL;
|
|
map->addr = gbm_bo_map(map->gbmbo, 0, 0, map->gbm_import_data.width,
|
|
map->gbm_import_data.height, GBM_BO_TRANSFER_READ,
|
|
&ret_stride, &map->gbm_map_data);
|
|
if (!map->addr) {
|
|
gbm_bo_destroy(map->gbmbo);
|
|
return false;
|
|
}
|
|
|
|
map->stride[0] = ret_stride;
|
|
map->size = ret_stride * map->gbm_import_data.height;
|
|
|
|
return true;
|
|
}
|
|
|
|
void sl_mmap_end_access(struct sl_mmap* map) {
|
|
if (map->map_type != SL_MMAP_DRM_PRIME)
|
|
return;
|
|
|
|
if (map->addr && map->gbm_map_data) {
|
|
gbm_bo_unmap(map->gbmbo, map->gbm_map_data);
|
|
map->addr = NULL;
|
|
map->gbm_map_data = NULL;
|
|
}
|
|
|
|
if (map->gbmbo) {
|
|
gbm_bo_destroy(map->gbmbo);
|
|
map->gbmbo = NULL;
|
|
}
|
|
}
|
|
|
|
void sl_mmap_unref(struct sl_mmap* map) {
|
|
TRACE_EVENT("shm", "sl_mmap_unref");
|
|
if (map->refcount-- == 1) {
|
|
switch (map->map_type) {
|
|
case SL_MMAP_SHM:
|
|
munmap(map->addr, map->size + map->offset[0]);
|
|
if (map->fd != -1)
|
|
close(map->fd);
|
|
delete map;
|
|
break;
|
|
|
|
case SL_MMAP_DRM_PRIME:
|
|
// Invoke end_access just in case
|
|
sl_mmap_end_access(map);
|
|
if (map->fd != -1)
|
|
close(map->fd);
|
|
delete map;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|