Skip to content
Draft
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
4 changes: 4 additions & 0 deletions src/egl/drivers/dri2/platform_x11_dri3.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@
#include "x11_dri3.h"
#include "loader_dri3_helper.h"

/* Keep the private EGL frontend tied to the DRI bridge structure ABI. */
const char hdmi_los_mesa_egl_bridge_abi[]
__attribute__((used, retain)) = LOADER_DRI3_SHM_BRIDGE_ABI;

static struct dri3_egl_surface *
loader_drawable_to_egl_surface(struct loader_dri3_drawable *draw)
{
Expand Down
1 change: 0 additions & 1 deletion src/freedreno/drm/freedreno_bo.c
Original file line number Diff line number Diff line change
Expand Up @@ -844,4 +844,3 @@ fd_bo_state(struct fd_bo *bo)

return FD_BO_STATE_BUSY;
}

20 changes: 12 additions & 8 deletions src/freedreno/drm/freedreno_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,11 @@ fd_device_new(int fd)
* on the first capability query. When kgsl is forced (the whole kgsl stack
* exports FD_FORCE_KGSL=1), ignore the fd we were handed and open the kgsl
* GPU node directly for rendering. The fd we were handed is kept as the
* device control/identity fd (dev->control_fd, returned by fd_device_fd):
* device control/identity fd (dev->control_fd):
* it still identifies the screen for u_pipe_screen_lookup_or_create()'s
* fd-keyed cache (which compares file descriptions, so dev->fd MUST stay a
* dup of the cache key - a freshly opened kgsl fd is a different file
* description and would break cache eviction -> use-after-free) and is the
* fd handed to DRI3 clients. Only GPU submission uses the kgsl fd. */
* fd-keyed cache (which compares file descriptions, so the screen's
* get_screen_fd callback must return this control fd) and is the fd handed
* to DRI3 clients. */
if (debug_get_bool_option("FD_FORCE_KGSL", false)) {
int kgsl_fd = open("/dev/kgsl-3d0", O_RDWR | O_CLOEXEC);
if (kgsl_fd >= 0) {
Expand Down Expand Up @@ -296,9 +295,14 @@ fd_device_del(struct fd_device *dev)
int
fd_device_fd(struct fd_device *dev)
{
/* Return the control/identity fd, not the GPU submission fd. On the kgsl
* stack these differ: the screen cache and DRI3 must see the fd we were
* handed (a dup of the cache key), while GPU submission uses dev->fd. */
return dev->fd;
}

int
fd_device_control_fd(struct fd_device *dev)
{
/* The KGSL backend submits through dev->fd while the DRI/KMS winsys and
* fd-keyed screen cache must retain the DRM fd supplied by the loader. */
return dev->control_fd;
}

Expand Down
1 change: 1 addition & 0 deletions src/freedreno/drm/freedreno_drmif.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ struct fd_device *fd_device_ref(struct fd_device *dev);
void fd_device_purge(struct fd_device *dev);
void fd_device_del(struct fd_device *dev);
int fd_device_fd(struct fd_device *dev);
int fd_device_control_fd(struct fd_device *dev);

enum fd_version {
FD_VERSION_MADVISE = 1, /* kernel supports madvise */
Expand Down
3 changes: 1 addition & 2 deletions src/freedreno/drm/freedreno_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ submit_offset(struct fd_bo *bo, uint32_t offset)

struct fd_device {
int fd; /* GPU submission fd (kgsl GPU node on the kgsl stack) */
int control_fd; /* screen-cache / DRI3 identity fd; == fd unless redirected */
int control_fd; /* screen-cache / DRI/KMS fd; == fd unless redirected */
enum fd_version version;
int32_t refcnt;
uint32_t features;
Expand Down Expand Up @@ -424,7 +424,6 @@ struct fd_bo_funcs {
uint64_t (*iova)(struct fd_bo *bo);
void (*set_name)(struct fd_bo *bo, const char *fmt, va_list ap);
int (*dmabuf)(struct fd_bo *bo);

/**
* Optional hook that is called before ->destroy(). In the case of
* batch deletes (such as BO cache cleanup or cleaning up a submit)
Expand Down
76 changes: 75 additions & 1 deletion src/gallium/drivers/freedreno/freedreno_screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

#include "util/format/u_format.h"
#include "util/format/u_format_s3tc.h"
#include "util/libdrm.h"
#include "util/os_file.h"
#include "util/os_misc.h"
#include "util/u_debug.h"
#include "util/u_inlines.h"
Expand All @@ -25,6 +27,7 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "drm-uapi/drm_fourcc.h"

#include "freedreno_fence.h"
Expand Down Expand Up @@ -86,6 +89,66 @@ static const struct debug_named_value fd_debug_options[] = {
};
/* clang-format on */

static void
fd_kgsl_renderonly_destroy(struct renderonly *ro)
{
if (ro->kms_fd >= 0)
close(ro->kms_fd);

util_sparse_array_finish(&ro->bo_map);
FREE(ro);
}

/*
* Android KGSL submits GPU work through /dev/kgsl-3d0 while scanout is owned
* by a separate DRM/KMS device. Model that split with Mesa's established
* renderonly contract instead of teaching the byte-oriented KGSL BO allocator
* how to manufacture display buffers. The fd supplied to this screen is the
* DRI3/KMS control fd; duplicating it preserves the GEM handle namespace used
* by the X server while render submissions continue through screen->dev->fd.
*/
static struct renderonly *
fd_kgsl_renderonly_create(int kms_fd)
{
struct renderonly *ro = CALLOC_STRUCT(renderonly);

if (!ro)
return NULL;

ro->kms_fd = os_dupfd_cloexec(kms_fd);
ro->gpu_fd = -1;
if (ro->kms_fd < 0) {
FREE(ro);
return NULL;
}

ro->create_for_resource =
renderonly_create_kms_dumb_buffer_for_resource;
ro->destroy = fd_kgsl_renderonly_destroy;
util_sparse_array_init(&ro->bo_map,
sizeof(struct renderonly_scanout), 64);
simple_mtx_init(&ro->bo_map_lock, mtx_plain);
return ro;
}

static bool
fd_kgsl_has_kms_control_fd(struct fd_device *dev)
{
drmVersionPtr version = drmGetVersion(fd_device_control_fd(dev));
/*
* Mainline names this DRM driver "msm". Qualcomm's downstream display
* stack, including the Sony pdx234 kernel, reports "msm_drm" instead.
* Both expose the KMS/dumb-buffer interface needed by renderonly.
*/
bool has_kms = version &&
(!strcmp(version->name, "msm") ||
!strcmp(version->name, "msm_drm"));

if (version)
drmFreeVersion(version);
return has_kms;
}

DEBUG_GET_ONCE_FLAGS_OPTION(fd_mesa_debug, "FD_MESA_DEBUG", fd_debug_options, 0)

int fd_mesa_debug = 0;
Expand Down Expand Up @@ -937,7 +1000,7 @@ static int
fd_screen_get_fd(struct pipe_screen *pscreen)
{
struct fd_screen *screen = fd_screen(pscreen);
return fd_device_fd(screen->dev);
return fd_device_control_fd(screen->dev);
}

static void
Expand Down Expand Up @@ -985,6 +1048,17 @@ fd_screen_create(int fd,
screen->dev = dev;
screen->is_kgsl = fd_get_features(dev) & FD_FEATURE_KGSL;
screen->kgsl_dmabuf = screen->is_kgsl && fd_kgsl_dmabuf_enabled();
if (!ro && screen->is_kgsl && fd_kgsl_has_kms_control_fd(dev) &&
debug_get_bool_option("FD_KGSL_RENDERONLY", false)) {
ro = fd_kgsl_renderonly_create(fd_device_control_fd(dev));
if (!ro) {
mesa_loge("freedreno/kgsl: failed to create KMS renderonly screen");
fd_device_del(dev);
FREE(screen);
return NULL;
}
mesa_logi("freedreno/kgsl: using Mesa renderonly for KMS scanout");
}
screen->ro = ro;

// maybe this should be in context?
Expand Down
2 changes: 1 addition & 1 deletion src/gallium/frontends/dri/dri2.c
Original file line number Diff line number Diff line change
Expand Up @@ -1548,7 +1548,7 @@ dri2_blit_image(struct dri_context *ctx, struct dri_image *dst, struct dri_image
{
struct pipe_context *pipe = ctx->st->pipe;
struct pipe_screen *screen;
struct pipe_fence_handle *fence;
struct pipe_fence_handle *fence = NULL;
struct pipe_blit_info blit;

if (!dst || !src)
Expand Down
Loading