Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/freedreno/drm/freedreno_drmif.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ void fd_device_disable_explicit_sync_heuristic(struct fd_device *dev);
enum fd_features {
FD_FEATURE_DIRECT_RESET = 1,
FD_FEATURE_IMPORT_DMABUF = 2,
FD_FEATURE_KGSL = 4,
};

uint32_t fd_get_features(struct fd_device *dev);
Expand Down
4 changes: 4 additions & 0 deletions src/freedreno/drm/kgsl/kgsl_bo.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ kgsl_bo_map(struct fd_bo *bo)

static int kgsl_bo_dmabuf(struct fd_bo *bo) {
struct kgsl_bo *kgsl_bo = to_kgsl_bo(bo);

if (kgsl_bo->bo_type != KGSL_BO_IMPORT || kgsl_bo->import_fd < 0)
return -1;

return os_dupfd_cloexec(kgsl_bo->import_fd);
}

Expand Down
2 changes: 1 addition & 1 deletion src/freedreno/drm/kgsl/kgsl_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ kgsl_device_new(int fd)
dev->funcs = &funcs;
dev->fd = fd;
dev->version = FD_VERSION_ROBUSTNESS;
dev->features = FD_FEATURE_DIRECT_RESET | FD_FEATURE_IMPORT_DMABUF;
dev->features = FD_FEATURE_DIRECT_RESET | FD_FEATURE_IMPORT_DMABUF | FD_FEATURE_KGSL;

/* async submit_queue used for softpin deffered submits */
util_queue_init(&dev->submit_queue, "sq", 8, 1, 0, NULL);
Expand Down
49 changes: 49 additions & 0 deletions src/gallium/drivers/freedreno/freedreno_resource.c
Original file line number Diff line number Diff line change
Expand Up @@ -1080,6 +1080,15 @@ fd_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *prsc)
static uint64_t
fd_resource_modifier(struct fd_resource *rsc)
{
struct fd_screen *screen = fd_screen(rsc->b.b.screen);

if (screen->kgsl_dmabuf) {
if (rsc->layout.tile_mode == 0 && !rsc->layout.ubwc_layer_size)
return DRM_FORMAT_MOD_LINEAR;

return DRM_FORMAT_MOD_INVALID;
}

if (rsc->layout.ubwc_layer_size)
return DRM_FORMAT_MOD_QCOM_COMPRESSED;

Expand All @@ -1106,6 +1115,23 @@ fd_resource_get_handle(struct pipe_screen *pscreen, struct pipe_context *pctx,

handle->modifier = fd_resource_modifier(rsc);

if (fd_screen(pscreen)->kgsl_dmabuf) {
handle->modifier = DRM_FORMAT_MOD_LINEAR;

if (!(prsc->bind & PIPE_BIND_SHARED)) {
struct fd_context *ctx = fd_screen_aux_context_get(pscreen);

prsc->bind |= PIPE_BIND_SHARED;

bool ret = fd_try_shadow_resource(ctx, rsc, 0, NULL, handle->modifier);

fd_screen_aux_context_put(pscreen);

if (!ret)
return false;
}
}

if (prsc->target != PIPE_BUFFER) {
struct fdl_metadata metadata = {
.modifier = handle->modifier,
Expand Down Expand Up @@ -1311,6 +1337,20 @@ get_best_layout(struct fd_screen *screen,
if (FD_DBG(NOTILE))
return FD_LAYOUT_LINEAR;

if (screen->kgsl_dmabuf &&
(tmpl->bind & (PIPE_BIND_SHARED | PIPE_BIND_SCANOUT))) {
if (has_implicit_modifier(modifiers, count) ||
drm_find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count)) {
perf_debug("%" PRSC_FMT ": forcing linear: kgsl shared/scanout resource",
PRSC_ARGS(tmpl));
return FD_LAYOUT_LINEAR;
}

perf_debug("%" PRSC_FMT ": kgsl shared/scanout resource requires linear",
PRSC_ARGS(tmpl));
return FD_LAYOUT_ERROR;
}

/* Shared resources without explicit modifiers must always be linear */
if (!can_explicit && (tmpl->bind & PIPE_BIND_SHARED)) {
perf_debug("%" PRSC_FMT
Expand Down Expand Up @@ -1529,6 +1569,15 @@ fd_resource_from_handle(struct pipe_screen *pscreen,

DBG("%" PRSC_FMT ", modifier=%" PRIx64, PRSC_ARGS(prsc), handle->modifier);

if (screen->kgsl_dmabuf &&
handle->modifier != DRM_FORMAT_MOD_LINEAR &&
handle->modifier != DRM_FORMAT_MOD_INVALID) {
if (FD_DBG(LAYOUT))
mesa_loge("kgsl cannot import non-linear modifier %" PRIx64,
handle->modifier);
goto fail;
}

rsc->b.is_shared = true;

struct fd_bo *bo = fd_screen_bo_from_handle(pscreen, handle);
Expand Down
50 changes: 42 additions & 8 deletions src/gallium/drivers/freedreno/freedreno_screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ DEBUG_GET_ONCE_FLAGS_OPTION(fd_mesa_debug, "FD_MESA_DEBUG", fd_debug_options, 0)
int fd_mesa_debug = 0;
bool fd_binning_enabled = true;

static bool
fd_kgsl_dmabuf_enabled(void)
{
return debug_get_bool_option("FD_KGSL_ENABLE_DMABUF", false) ||
debug_get_bool_option("XWAYLAND_FORCE_KGSL_SURFACELESS", false);
}

static const char *
fd_screen_get_name(struct pipe_screen *pscreen)
{
Expand Down Expand Up @@ -383,14 +390,15 @@ fd_init_screen_caps(struct fd_screen *screen)

u_init_pipe_screen_caps(&screen->base, 1);

/* On the kgsl stack the screen's control fd is the sde-kms display node
* (renderD128); drmGetCap(DRM_CAP_PRIME) there does not report the GPU's
* real PRIME import/export support, so u_init_pipe_screen_caps() leaves
* caps.dmabuf unset and EGL never advertises EGL_EXT_image_dma_buf_import
* (which kwin/GL compositors need to import client buffers). The kgsl
* backend does support dmabuf import/export (FD_FEATURE_IMPORT_DMABUF), so
* force the cap on. */
caps->dmabuf = 0x1 /*DRM_PRIME_CAP_IMPORT*/ | 0x2 /*DRM_PRIME_CAP_EXPORT*/;
/* On the kgsl stack the screen's control fd may be a display/controller fd
* rather than the kgsl GPU fd, so drmGetCap(DRM_CAP_PRIME) cannot describe
* the backend's real import/export support. The kgsl backend allocates
* shared buffers from dma-heap/ION and imports them into KGSL, so advertise
* dmabuf support only for that path. */
if (screen->kgsl_dmabuf) {
caps->dmabuf =
0x1 /*DRM_PRIME_CAP_IMPORT*/ | 0x2 /*DRM_PRIME_CAP_EXPORT*/;
}

/* this is probably not totally correct.. but it's a start: */

Expand Down Expand Up @@ -819,6 +827,23 @@ fd_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen,
uint64_t *modifiers,
unsigned int *external_only, int *count)
{
struct fd_screen *screen = fd_screen(pscreen);

if (screen->kgsl_dmabuf) {
*count = is_format_supported(pscreen, format,
DRM_FORMAT_MOD_LINEAR) ? 1 : 0;

if (*count && max > 0) {
if (modifiers)
modifiers[0] = DRM_FORMAT_MOD_LINEAR;

if (external_only)
external_only[0] = !is_rendering_supported(pscreen, format);
}

return;
}

const uint64_t all_modifiers[] = {
DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_QCOM_COMPRESSED,
Expand Down Expand Up @@ -851,6 +876,13 @@ fd_screen_is_dmabuf_modifier_supported(struct pipe_screen *pscreen,
enum pipe_format format,
bool *external_only)
{
struct fd_screen *screen = fd_screen(pscreen);

if (screen->kgsl_dmabuf &&
modifier != DRM_FORMAT_MOD_LINEAR &&
modifier != DRM_FORMAT_MOD_INVALID)
return false;

return is_format_supported(pscreen, format, modifier);
}

Expand Down Expand Up @@ -951,6 +983,8 @@ fd_screen_create(int fd,
pscreen = &screen->base;

screen->dev = dev;
screen->is_kgsl = fd_get_features(dev) & FD_FEATURE_KGSL;
screen->kgsl_dmabuf = screen->is_kgsl && fd_kgsl_dmabuf_enabled();
screen->ro = ro;

// maybe this should be in context?
Expand Down
2 changes: 2 additions & 0 deletions src/gallium/drivers/freedreno/freedreno_screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ struct fd_screen {
bool has_timestamp;
bool has_robustness;
bool has_syncobj;
bool is_kgsl;
bool kgsl_dmabuf;

struct {
/* Conservative LRZ (default true) invalidates LRZ on draws with
Expand Down