mirror of
https://github.com/X11Libre/xserver.git
synced 2026-03-24 08:04:30 +00:00
modesetting: Add infrastructure for creating and mapping gbm bo's
Signed-off-by: stefan11111 <stefan11111@shitposting.expert>
This commit is contained in:
committed by
Enrico Weigelt
parent
55eba2385c
commit
a1872f51fb
332
hw/xfree86/drivers/video/modesetting/drmmode_bo.c
Normal file
332
hw/xfree86/drivers/video/modesetting/drmmode_bo.c
Normal file
@@ -0,0 +1,332 @@
|
||||
/* SPDX-License-Identifier: MIT OR X11
|
||||
*
|
||||
* Copyright © 2026 stefan11111 <stefan11111@shitposting.expert>
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "dix-config.h"
|
||||
|
||||
#include "dix.h" /* ARRAY_SIZE() */
|
||||
|
||||
#include "dix/dix_priv.h"
|
||||
|
||||
#include <drm_fourcc.h>
|
||||
#include <drm_mode.h>
|
||||
|
||||
#include <xf86drm.h>
|
||||
#include "xf86Crtc.h"
|
||||
|
||||
#include "driver.h"
|
||||
#include "drmmode_bo.h"
|
||||
|
||||
typedef struct {
|
||||
void* map_data; /* Opaque ptr for the mapped region */
|
||||
void* map_addr; /* Address of the map, what we actually want to use */
|
||||
Bool used_modifiers;
|
||||
} bo_priv_t;
|
||||
|
||||
#ifndef GBM_BO_USE_LINEAR
|
||||
#define GBM_BO_USE_LINEAR 0
|
||||
#endif
|
||||
|
||||
#ifndef GBM_BO_USE_FRONT_RENDERING
|
||||
#define GBM_BO_USE_FRONT_RENDERING 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Thin wrapper around gbm_bo_{create,map,unmap}
|
||||
* that creates and maps (if necessary) the "best"
|
||||
* buffer of a certain type that we can create.
|
||||
*
|
||||
* Any needed mapping is done when creating the buffer,
|
||||
* and unmapping is handeled automatically by the gbm
|
||||
* loader through the destroy_user_data callback.
|
||||
*/
|
||||
|
||||
#define TRY_CREATE(proc, data, do_map, ...) \
|
||||
do { \
|
||||
struct gbm_bo *ret = (proc)(__VA_ARGS__); \
|
||||
if (ret && (!(do_map) || gbm_bo_map_or_free(ret, (data)))) { \
|
||||
return ret; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
static inline uint32_t
|
||||
get_opaque_format(uint32_t format)
|
||||
{
|
||||
switch (format) {
|
||||
case DRM_FORMAT_ARGB8888:
|
||||
return DRM_FORMAT_XRGB8888;
|
||||
case DRM_FORMAT_ARGB2101010:
|
||||
return DRM_FORMAT_XRGB2101010;
|
||||
default:
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_user_data(struct gbm_bo *bo, void* _data)
|
||||
{
|
||||
bo_priv_t *data = _data;
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->map_data) {
|
||||
gbm_bo_unmap(bo, data->map_data);
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
|
||||
void*
|
||||
gbm_bo_get_map(struct gbm_bo *bo)
|
||||
{
|
||||
bo_priv_t *data = gbm_bo_get_user_data(bo);
|
||||
return data ? data->map_addr : NULL;
|
||||
}
|
||||
|
||||
Bool
|
||||
gbm_bo_get_used_modifiers(struct gbm_bo *bo)
|
||||
{
|
||||
bo_priv_t *data = gbm_bo_get_user_data(bo);
|
||||
return data ? data->used_modifiers : FALSE;
|
||||
}
|
||||
|
||||
static inline Bool
|
||||
gbm_bo_map_all(struct gbm_bo *bo, bo_priv_t *data)
|
||||
{
|
||||
uint32_t stride = 0;
|
||||
|
||||
if (!bo || !data) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (data->map_addr) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
uint32_t width = gbm_bo_get_width(bo);
|
||||
uint32_t height = gbm_bo_get_height(bo);
|
||||
|
||||
/* must be NULL before the map call */
|
||||
data->map_data = NULL;
|
||||
|
||||
/* While reading from gpu memory is often very slow, we do allow it */
|
||||
data->map_addr = gbm_bo_map(bo, 0, 0, width, height,
|
||||
GBM_BO_TRANSFER_READ_WRITE,
|
||||
&stride, &data->map_data);
|
||||
|
||||
return !!data->map_addr;
|
||||
}
|
||||
|
||||
static inline Bool
|
||||
gbm_bo_map_or_free(struct gbm_bo *bo, bo_priv_t *data)
|
||||
{
|
||||
if (gbm_bo_map_all(bo, data)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (bo) {
|
||||
gbm_bo_destroy(bo);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static inline struct gbm_bo*
|
||||
gbm_bo_create_and_map(struct gbm_device *gbm,
|
||||
bo_priv_t *data,
|
||||
Bool do_map,
|
||||
uint32_t width, uint32_t height,
|
||||
uint32_t format,
|
||||
const uint64_t *modifiers,
|
||||
const unsigned int count,
|
||||
uint32_t flags)
|
||||
{
|
||||
if (!data) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef GBM_BO_WITH_MODIFIERS
|
||||
if (count && modifiers) {
|
||||
data->used_modifiers = TRUE;
|
||||
#ifdef GBM_BO_WITH_MODIFIERS2
|
||||
TRY_CREATE(gbm_bo_create_with_modifiers2, data, do_map,
|
||||
gbm, width, height, format, modifiers, count, flags);
|
||||
#endif
|
||||
TRY_CREATE(gbm_bo_create_with_modifiers, data, do_map,
|
||||
gbm, width, height, format, modifiers, count);
|
||||
}
|
||||
#endif
|
||||
|
||||
data->used_modifiers = FALSE;
|
||||
TRY_CREATE(gbm_bo_create, data, do_map,
|
||||
gbm, width, height, format, flags);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct gbm_bo*
|
||||
gbm_bo_create_and_map_with_flag_list(struct gbm_device *gbm,
|
||||
bo_priv_t *data,
|
||||
Bool do_map,
|
||||
uint32_t width, uint32_t height,
|
||||
uint32_t format,
|
||||
const uint64_t *modifiers,
|
||||
const unsigned int count,
|
||||
const uint32_t *flag_list,
|
||||
unsigned int flag_count)
|
||||
{
|
||||
struct gbm_bo *ret = NULL;
|
||||
for (unsigned int i = 0; i < flag_count && !ret; i++) {
|
||||
ret = gbm_bo_create_and_map(gbm, data, do_map,
|
||||
width, height, format,
|
||||
modifiers, count,
|
||||
flag_list[i]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline struct gbm_bo*
|
||||
gbm_create_front_bo(drmmode_ptr drmmode, Bool do_map,
|
||||
bo_priv_t *data,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
uint32_t format = drmmode_gbm_format_for_depth(drmmode->scrn->depth);
|
||||
|
||||
uint32_t num_modifiers = 0;
|
||||
uint64_t *modifiers = NULL;
|
||||
|
||||
static const uint32_t front_flag_list[] = { /* best flags */
|
||||
GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT |
|
||||
GBM_BO_USE_FRONT_RENDERING,
|
||||
|
||||
/* if front_rendering is unsupported */
|
||||
GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT,
|
||||
|
||||
/* linear buffers */
|
||||
GBM_BO_USE_LINEAR | GBM_BO_USE_SCANOUT |
|
||||
GBM_BO_USE_FRONT_RENDERING,
|
||||
|
||||
GBM_BO_USE_WRITE | GBM_BO_USE_SCANOUT,
|
||||
};
|
||||
|
||||
#ifdef GBM_BO_WITH_MODIFIERS
|
||||
num_modifiers = get_modifiers_set(drmmode->scrn, format, &modifiers,
|
||||
FALSE, TRUE, TRUE);
|
||||
#endif
|
||||
|
||||
return gbm_bo_create_and_map_with_flag_list(drmmode->gbm,
|
||||
data,
|
||||
do_map,
|
||||
width, height,
|
||||
format,
|
||||
modifiers, num_modifiers,
|
||||
front_flag_list,
|
||||
ARRAY_SIZE(front_flag_list));
|
||||
}
|
||||
static inline struct gbm_bo*
|
||||
gbm_create_cursor_bo(drmmode_ptr drmmode, Bool do_map,
|
||||
bo_priv_t *data,
|
||||
uint32_t width, uint32_t height)
|
||||
{
|
||||
static const uint32_t cursor_flag_list[] = { /* best flags */
|
||||
GBM_BO_USE_CURSOR,
|
||||
|
||||
#if 0 /* Use these ones too if we ever need to */
|
||||
GBM_BO_USE_CURSOR | GBM_BO_USE_LINEAR,
|
||||
GBM_BO_USE_LINEAR,
|
||||
#endif
|
||||
|
||||
/* For older mesa */
|
||||
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE,
|
||||
};
|
||||
|
||||
/* Assume whatever bpp we have for the primary plane, we also have for the cursor plane */
|
||||
int bpp = drmmode->kbpp;
|
||||
|
||||
/**
|
||||
* Assume the depth for the cursor is the same as the bpp,
|
||||
* even if this is not true for the primary plane (e.g., even if bpp is 32, but drmmode->scrn->depth is 24).
|
||||
*/
|
||||
uint32_t format = drmmode_gbm_format_for_depth(bpp);
|
||||
|
||||
return gbm_bo_create_and_map_with_flag_list(drmmode->gbm,
|
||||
data,
|
||||
do_map,
|
||||
width, height,
|
||||
format,
|
||||
NULL, 0,
|
||||
cursor_flag_list,
|
||||
ARRAY_SIZE(cursor_flag_list));
|
||||
}
|
||||
|
||||
struct gbm_bo*
|
||||
gbm_create_best_bo(drmmode_ptr drmmode, Bool do_map,
|
||||
uint32_t width, uint32_t height,
|
||||
int type)
|
||||
{
|
||||
struct gbm_bo *ret = NULL;
|
||||
bo_priv_t* data = calloc(1, sizeof(*data));
|
||||
if (!data) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case DRMMODE_FRONT_BO:
|
||||
ret = gbm_create_front_bo(drmmode, do_map, data, width, height);
|
||||
break;
|
||||
case DRMMODE_CURSOR_BO:
|
||||
ret = gbm_create_cursor_bo(drmmode, do_map, data, width, height);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gbm_bo_set_user_data(ret, data, destroy_user_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* dmabuf import */
|
||||
struct gbm_bo*
|
||||
gbm_back_bo_from_fd(drmmode_ptr drmmode, Bool do_map, int fd_handle, uint32_t pitch, uint32_t size)
|
||||
{
|
||||
/* pitch == width * cpp */
|
||||
int width = pitch / drmmode->cpp;
|
||||
/* size == pitch * height */
|
||||
int height = size / pitch;
|
||||
|
||||
int depth = drmmode->scrn->depth > 0 ?
|
||||
drmmode->scrn->depth : drmmode->kbpp;
|
||||
|
||||
uint32_t format = drmmode_gbm_format_for_depth(depth);
|
||||
|
||||
struct gbm_import_fd_data import_data = {.fd = fd_handle,
|
||||
.width = width,
|
||||
.height = height,
|
||||
.stride = pitch,
|
||||
.format = format,
|
||||
};
|
||||
|
||||
bo_priv_t* data = calloc(1, sizeof(*data));
|
||||
if (!data) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data->used_modifiers = FALSE;
|
||||
|
||||
TRY_CREATE(gbm_bo_import, data, do_map,
|
||||
drmmode->gbm, GBM_BO_IMPORT_FD, &import_data,
|
||||
GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT);
|
||||
|
||||
TRY_CREATE(gbm_bo_import, data, do_map,
|
||||
drmmode->gbm, GBM_BO_IMPORT_FD, &import_data,
|
||||
GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT | GBM_BO_USE_WRITE);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
58
hw/xfree86/drivers/video/modesetting/drmmode_bo.h
Normal file
58
hw/xfree86/drivers/video/modesetting/drmmode_bo.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* SPDX-License-Identifier: MIT OR X11
|
||||
*
|
||||
* Copyright © 2026 stefan11111 <stefan11111@shitposting.expert>
|
||||
*/
|
||||
|
||||
#ifndef DRMMODE_BO_H
|
||||
#define DRMMODE_BO_H
|
||||
|
||||
#include <gbm.h>
|
||||
#include "drmmode_display.h"
|
||||
|
||||
enum {
|
||||
DRMMODE_FRONT_BO = 1 << 0,
|
||||
DRMMODE_CURSOR_BO = 1 << 1,
|
||||
DRMMODE_SHADOW_BO = 1 << 2,
|
||||
};
|
||||
|
||||
void*
|
||||
gbm_bo_get_map(struct gbm_bo *bo);
|
||||
|
||||
Bool
|
||||
gbm_bo_get_used_modifiers(struct gbm_bo *bo);
|
||||
|
||||
/* Create the best gbm bo of a given type */
|
||||
struct gbm_bo*
|
||||
gbm_create_best_bo(drmmode_ptr drmmode, Bool do_map,
|
||||
uint32_t width, uint32_t height,
|
||||
int type);
|
||||
|
||||
/* dmabuf import */
|
||||
struct gbm_bo*
|
||||
gbm_back_bo_from_fd(drmmode_ptr drmmode, Bool do_map,
|
||||
int fd_handle, uint32_t pitch, uint32_t size);
|
||||
|
||||
static inline uint32_t
|
||||
drmmode_gbm_format_for_depth(int depth)
|
||||
{
|
||||
switch (depth) {
|
||||
case 8:
|
||||
return GBM_FORMAT_R8;
|
||||
case 15:
|
||||
return GBM_FORMAT_ARGB1555;
|
||||
case 16:
|
||||
return GBM_FORMAT_RGB565;
|
||||
case 24:
|
||||
return GBM_FORMAT_XRGB8888;
|
||||
case 30:
|
||||
/* XXX Is this format right? https://github.com/X11Libre/xserver/pull/1396/files#r2523698616 XXX */
|
||||
return GBM_FORMAT_ARGB2101010;
|
||||
case 32:
|
||||
return GBM_FORMAT_ARGB8888;
|
||||
}
|
||||
|
||||
/* Unsupported depth */
|
||||
return GBM_FORMAT_ARGB8888;
|
||||
}
|
||||
|
||||
#endif /* DRMMODE_BO_H */
|
||||
@@ -51,7 +51,7 @@
|
||||
|
||||
#include <xf86drm.h>
|
||||
#include "xf86Crtc.h"
|
||||
#include "drmmode_display.h"
|
||||
#include "drmmode_bo.h"
|
||||
|
||||
#include <cursorstr.h>
|
||||
|
||||
@@ -183,7 +183,7 @@ drmmode_is_format_supported(ScrnInfoPtr scrn, uint32_t format,
|
||||
}
|
||||
|
||||
#ifdef GBM_BO_WITH_MODIFIERS
|
||||
static uint32_t
|
||||
uint32_t
|
||||
get_modifiers_set(ScrnInfoPtr scrn, uint32_t format, uint64_t **modifiers,
|
||||
Bool enabled_crtc_only, Bool exclude_multiplane, Bool async_flip)
|
||||
{
|
||||
@@ -1162,29 +1162,6 @@ drmmode_bo_import(drmmode_ptr drmmode, drmmode_bo *bo,
|
||||
drmmode_bo_get_handle(bo), fb_id);
|
||||
}
|
||||
|
||||
#ifdef GLAMOR_HAS_GBM
|
||||
/* formats taken from glamor/glamor_egl.c */
|
||||
static inline uint32_t
|
||||
drmmode_gbm_format_for_depth(int depth)
|
||||
{
|
||||
switch (depth) {
|
||||
case 8:
|
||||
return GBM_FORMAT_R8;
|
||||
case 15:
|
||||
return GBM_FORMAT_ARGB1555;
|
||||
case 16:
|
||||
return GBM_FORMAT_RGB565;
|
||||
case 24:
|
||||
return GBM_FORMAT_XRGB8888;
|
||||
case 30:
|
||||
/* XXX Is this format right? https://github.com/X11Libre/xserver/pull/1396/files#r2523698616 XXX */
|
||||
return GBM_FORMAT_ARGB2101010;
|
||||
default:
|
||||
return GBM_FORMAT_ARGB8888;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static Bool
|
||||
drmmode_create_front_bo(drmmode_ptr drmmode, drmmode_bo *bo,
|
||||
unsigned width, unsigned height, unsigned bpp)
|
||||
|
||||
@@ -373,4 +373,11 @@ Bool drmmode_crtc_get_fb_id(xf86CrtcPtr crtc, uint32_t *fb_id, int *x, int *y);
|
||||
|
||||
void drmmode_set_dpms(ScrnInfoPtr scrn, int PowerManagementMode, int flags);
|
||||
void drmmode_crtc_set_vrr(xf86CrtcPtr crtc, Bool enabled);
|
||||
|
||||
#ifdef GBM_BO_WITH_MODIFIERS
|
||||
uint32_t
|
||||
get_modifiers_set(ScrnInfoPtr scrn, uint32_t format, uint64_t **modifiers,
|
||||
Bool enabled_crtc_only, Bool exclude_multiplane, Bool async_flip);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
modesetting_srcs = [
|
||||
'dri2.c',
|
||||
'driver.c',
|
||||
'drmmode_bo.c',
|
||||
'drmmode_display.c',
|
||||
'dumb_bo.c',
|
||||
'pageflip.c',
|
||||
|
||||
Reference in New Issue
Block a user