sync code with last improvements from OpenBSD

This commit is contained in:
purplerain 2023-08-28 05:57:34 +00:00
commit 88965415ff
Signed by: purplerain
GPG key ID: F42C07F07E2E35B7
26235 changed files with 29195616 additions and 0 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,198 @@
/*
* Copyright © 2011 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Benjamin Franzke <benjaminfranzke@googlemail.com>
*/
#ifndef _GBM_DRI_INTERNAL_H_
#define _GBM_DRI_INTERNAL_H_
#include <xf86drm.h>
#include <string.h>
#include <sys/mman.h>
#include "gbmint.h"
#include "c11/threads.h"
#include <GL/gl.h> /* dri_interface needs GL types */
#include "GL/internal/dri_interface.h"
#include "kopper_interface.h"
struct gbm_dri_surface;
struct gbm_dri_bo;
struct gbm_dri_visual {
uint32_t gbm_format;
int dri_image_format;
struct {
int red;
int green;
int blue;
int alpha;
} rgba_shifts;
struct {
unsigned int red;
unsigned int green;
unsigned int blue;
unsigned int alpha;
} rgba_sizes;
bool is_float;
};
struct gbm_dri_device {
struct gbm_device base;
void *driver;
char *driver_name; /* Name of the DRI module, without the _dri suffix */
bool software; /* A software driver was loaded */
__DRIscreen *screen;
__DRIcontext *context;
mtx_t mutex;
const __DRIcoreExtension *core;
const __DRIdri2Extension *dri2;
const __DRI2fenceExtension *fence;
const __DRIimageExtension *image;
const __DRIswrastExtension *swrast;
const __DRIkopperExtension *kopper;
const __DRI2flushExtension *flush;
const __DRIconfig **driver_configs;
const __DRIextension **loader_extensions;
const __DRIextension **driver_extensions;
__DRIimage *(*lookup_image)(__DRIscreen *screen, void *image, void *data);
GLboolean (*validate_image)(void *image, void *data);
__DRIimage *(*lookup_image_validated)(void *image, void *data);
void *lookup_user_data;
__DRIbuffer *(*get_buffers)(__DRIdrawable * driDrawable,
int *width, int *height,
unsigned int *attachments, int count,
int *out_count, void *data);
void (*flush_front_buffer)(__DRIdrawable * driDrawable, void *data);
__DRIbuffer *(*get_buffers_with_format)(__DRIdrawable * driDrawable,
int *width, int *height,
unsigned int *attachments, int count,
int *out_count, void *data);
int (*image_get_buffers)(__DRIdrawable *driDrawable,
unsigned int format,
uint32_t *stamp,
void *loaderPrivate,
uint32_t buffer_mask,
struct __DRIimageList *buffers);
void (*swrast_put_image2)(__DRIdrawable *driDrawable,
int op,
int x,
int y,
int width,
int height,
int stride,
char *data,
void *loaderPrivate);
void (*swrast_get_image)(__DRIdrawable *driDrawable,
int x,
int y,
int width,
int height,
char *data,
void *loaderPrivate);
struct wl_drm *wl_drm;
const struct gbm_dri_visual *visual_table;
int num_visuals;
};
struct gbm_dri_bo {
struct gbm_bo base;
__DRIimage *image;
/* Used for cursors and the swrast front BO */
uint32_t handle, size;
void *map;
};
struct gbm_dri_surface {
struct gbm_surface base;
void *dri_private;
};
static inline struct gbm_dri_device *
gbm_dri_device(struct gbm_device *gbm)
{
return (struct gbm_dri_device *) gbm;
}
static inline struct gbm_dri_bo *
gbm_dri_bo(struct gbm_bo *bo)
{
return (struct gbm_dri_bo *) bo;
}
static inline struct gbm_dri_surface *
gbm_dri_surface(struct gbm_surface *surface)
{
return (struct gbm_dri_surface *) surface;
}
static inline void *
gbm_dri_bo_map_dumb(struct gbm_dri_bo *bo)
{
struct drm_mode_map_dumb map_arg;
int ret;
if (bo->image != NULL)
return NULL;
if (bo->map != NULL)
return bo->map;
memset(&map_arg, 0, sizeof(map_arg));
map_arg.handle = bo->handle;
ret = drmIoctl(bo->base.gbm->v0.fd, DRM_IOCTL_MODE_MAP_DUMB, &map_arg);
if (ret)
return NULL;
bo->map = mmap(NULL, bo->size, PROT_WRITE,
MAP_SHARED, bo->base.gbm->v0.fd, map_arg.offset);
if (bo->map == MAP_FAILED) {
bo->map = NULL;
return NULL;
}
return bo->map;
}
static inline void
gbm_dri_bo_unmap_dumb(struct gbm_dri_bo *bo)
{
munmap(bo->map, bo->size);
bo->map = NULL;
}
#endif

View file

@ -0,0 +1,38 @@
gbm_bo_create
gbm_bo_create_with_modifiers
gbm_bo_create_with_modifiers2
gbm_bo_destroy
gbm_bo_get_bpp
gbm_bo_get_device
gbm_bo_get_fd
gbm_bo_get_fd_for_plane
gbm_bo_get_format
gbm_bo_get_handle
gbm_bo_get_handle_for_plane
gbm_bo_get_height
gbm_bo_get_modifier
gbm_bo_get_offset
gbm_bo_get_plane_count
gbm_bo_get_stride
gbm_bo_get_stride_for_plane
gbm_bo_get_user_data
gbm_bo_get_width
gbm_bo_import
gbm_bo_map
gbm_bo_set_user_data
gbm_bo_unmap
gbm_bo_write
gbm_create_device
gbm_device_destroy
gbm_device_get_backend_name
gbm_device_get_fd
gbm_device_get_format_modifier_plane_count
gbm_device_is_format_supported
gbm_format_get_name
gbm_surface_create
gbm_surface_create_with_modifiers
gbm_surface_create_with_modifiers2
gbm_surface_destroy
gbm_surface_has_free_buffers
gbm_surface_lock_front_buffer
gbm_surface_release_buffer

View file

@ -0,0 +1,238 @@
/*
* Copyright © 2011 Intel Corporation
* Copyright © 2021 NVIDIA Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Benjamin Franzke <benjaminfranzke@googlemail.com>
* James Jones <jajones@nvidia.com>
*/
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <assert.h>
#include <dlfcn.h>
#include <xf86drm.h>
#include "loader.h"
#include "backend.h"
#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
#define VER_MIN(a, b) ((a) < (b) ? (a) : (b))
extern const struct gbm_backend gbm_dri_backend;
struct gbm_backend_desc {
const char *name;
const struct gbm_backend *backend;
void *lib;
};
static const struct gbm_backend_desc builtin_backends[] = {
{ "dri", &gbm_dri_backend },
};
#define BACKEND_LIB_SUFFIX "_gbm"
static const char *backend_search_path_vars[] = {
"GBM_BACKENDS_PATH",
NULL
};
static void
free_backend_desc(const struct gbm_backend_desc *backend_desc)
{
assert(backend_desc->lib);
dlclose(backend_desc->lib);
free((void *)backend_desc->name);
free((void *)backend_desc);
}
static struct gbm_backend_desc *
create_backend_desc(const char *name,
const struct gbm_backend *backend,
void *lib)
{
struct gbm_backend_desc *new_desc = calloc(1, sizeof(*new_desc));
if (!new_desc)
return NULL;
new_desc->name = strdup(name);
if (!new_desc->name) {
free(new_desc);
return NULL;
}
new_desc->backend = backend;
new_desc->lib = lib;
return new_desc;
}
static struct gbm_device *
backend_create_device(const struct gbm_backend_desc *bd, int fd)
{
const uint32_t abi_ver = VER_MIN(GBM_BACKEND_ABI_VERSION,
bd->backend->v0.backend_version);
struct gbm_device *dev = bd->backend->v0.create_device(fd, abi_ver);
if (dev) {
if (abi_ver != dev->v0.backend_version) {
_gbm_device_destroy(dev);
return NULL;
}
dev->v0.backend_desc = bd;
}
return dev;
}
static struct gbm_device *
load_backend(void *lib, int fd, const char *name)
{
struct gbm_device *dev = NULL;
struct gbm_backend_desc *backend_desc;
const struct gbm_backend *gbm_backend;
GBM_GET_BACKEND_PROC_PTR get_backend;
get_backend = dlsym(lib, GBM_GET_BACKEND_PROC_NAME);
if (!get_backend)
goto fail;
gbm_backend = get_backend(&gbm_core);
backend_desc = create_backend_desc(name, gbm_backend, lib);
if (!backend_desc)
goto fail;
dev = backend_create_device(backend_desc, fd);
if (!dev)
free_backend_desc(backend_desc);
return dev;
fail:
dlclose(lib);
return NULL;
}
static struct gbm_device *
find_backend(const char *name, int fd)
{
struct gbm_device *dev = NULL;
const struct gbm_backend_desc *bd;
void *lib;
unsigned i;
for (i = 0; i < ARRAY_SIZE(builtin_backends); ++i) {
bd = &builtin_backends[i];
if (name && strcmp(bd->name, name))
continue;
dev = backend_create_device(bd, fd);
if (dev)
break;
}
if (name && !dev) {
lib = loader_open_driver_lib(name, BACKEND_LIB_SUFFIX,
backend_search_path_vars,
DEFAULT_BACKENDS_PATH,
true);
if (lib)
dev = load_backend(lib, fd, name);
}
return dev;
}
static struct gbm_device *
override_backend(int fd)
{
struct gbm_device *dev = NULL;
const char *b;
b = getenv("GBM_BACKEND");
if (b)
dev = find_backend(b, fd);
return dev;
}
static struct gbm_device *
backend_from_driver_name(int fd)
{
struct gbm_device *dev = NULL;
drmVersionPtr v = drmGetVersion(fd);
void *lib;
if (!v)
return NULL;
lib = loader_open_driver_lib(v->name, BACKEND_LIB_SUFFIX,
backend_search_path_vars,
DEFAULT_BACKENDS_PATH,
false);
if (lib)
dev = load_backend(lib, fd, v->name);
drmFreeVersion(v);
return dev;
}
struct gbm_device *
_gbm_create_device(int fd)
{
struct gbm_device *dev;
dev = override_backend(fd);
if (!dev)
dev = backend_from_driver_name(fd);
if (!dev)
dev = find_backend(NULL, fd);
return dev;
}
void
_gbm_device_destroy(struct gbm_device *gbm)
{
const struct gbm_backend_desc *backend_desc = gbm->v0.backend_desc;
gbm->v0.destroy(gbm);
if (backend_desc && backend_desc->lib)
free_backend_desc(backend_desc);
}

View file

@ -0,0 +1,39 @@
/*
* Copyright © 2011 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Benjamin Franzke <benjaminfranzke@googlemail.com>
*/
#ifndef MODULE_H_
#define MODULE_H_
#include "gbmint.h"
struct gbm_device *
_gbm_create_device(int fd);
void
_gbm_device_destroy(struct gbm_device *gbm);
#endif

837
lib/mesa/src/gbm/main/gbm.c Normal file
View file

@ -0,0 +1,837 @@
/*
* Copyright © 2011 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Benjamin Franzke <benjaminfranzke@googlemail.com>
*/
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#ifdef MAJOR_IN_MKDEV
#include <sys/mkdev.h>
#endif
#ifdef MAJOR_IN_SYSMACROS
#include <sys/sysmacros.h>
#endif
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include "gbm.h"
#include "gbmint.h"
#include "backend.h"
/** Returns the file description for the gbm device
*
* \return The fd that the struct gbm_device was created with
*/
GBM_EXPORT int
gbm_device_get_fd(struct gbm_device *gbm)
{
return gbm->v0.fd;
}
/** Get the backend name for the given gbm device
*
* \return The backend name string - this belongs to the device and must not
* be freed
*/
GBM_EXPORT const char *
gbm_device_get_backend_name(struct gbm_device *gbm)
{
return gbm->v0.name;
}
/** Test if a format is supported for a given set of usage flags.
*
* \param gbm The created buffer manager
* \param format The format to test
* \param flags A bitmask of the usages to test the format against
* \return 1 if the format is supported otherwise 0
*
* \sa enum gbm_bo_flags for the list of flags that the format can be
* tested against
*
* \sa enum gbm_bo_format for the list of formats
*/
GBM_EXPORT int
gbm_device_is_format_supported(struct gbm_device *gbm,
uint32_t format, uint32_t flags)
{
return gbm->v0.is_format_supported(gbm, format, flags);
}
/** Get the number of planes that are required for a given format+modifier
*
* \param gbm The gbm device returned from gbm_create_device()
* \param format The format to query
* \param modifier The modifier to query
*/
GBM_EXPORT int
gbm_device_get_format_modifier_plane_count(struct gbm_device *gbm,
uint32_t format,
uint64_t modifier)
{
return gbm->v0.get_format_modifier_plane_count(gbm, format, modifier);
}
/** Destroy the gbm device and free all resources associated with it.
*
* Prior to calling this function all buffers and surfaces created with the
* gbm device need to be destroyed.
*
* \param gbm The device created using gbm_create_device()
*/
GBM_EXPORT void
gbm_device_destroy(struct gbm_device *gbm)
{
_gbm_device_destroy(gbm);
}
/** Create a gbm device for allocating buffers
*
* The file descriptor passed in is used by the backend to communicate with
* platform for allocating the memory. For allocations using DRI this would be
* the file descriptor returned when opening a device such as \c
* /dev/dri/card0
*
* \param fd The file descriptor for a backend specific device
* \return The newly created struct gbm_device. The resources associated with
* the device should be freed with gbm_device_destroy() when it is no longer
* needed. If the creation of the device failed NULL will be returned.
*/
GBM_EXPORT struct gbm_device *
gbm_create_device(int fd)
{
struct gbm_device *gbm = NULL;
struct stat buf;
if (fd < 0 || fstat(fd, &buf) < 0 || !S_ISCHR(buf.st_mode)) {
errno = EINVAL;
return NULL;
}
gbm = _gbm_create_device(fd);
if (gbm == NULL)
return NULL;
gbm->dummy = gbm_create_device;
return gbm;
}
/** Get the width of the buffer object
*
* \param bo The buffer object
* \return The width of the allocated buffer object
*
*/
GBM_EXPORT uint32_t
gbm_bo_get_width(struct gbm_bo *bo)
{
return bo->v0.width;
}
/** Get the height of the buffer object
*
* \param bo The buffer object
* \return The height of the allocated buffer object
*/
GBM_EXPORT uint32_t
gbm_bo_get_height(struct gbm_bo *bo)
{
return bo->v0.height;
}
/** Get the stride of the buffer object
*
* This is calculated by the backend when it does the allocation in
* gbm_bo_create()
*
* \param bo The buffer object
* \return The stride of the allocated buffer object in bytes
*/
GBM_EXPORT uint32_t
gbm_bo_get_stride(struct gbm_bo *bo)
{
return gbm_bo_get_stride_for_plane(bo, 0);
}
/** Get the stride for the given plane
*
* \param bo The buffer object
* \param plane for which you want the stride
*
* \sa gbm_bo_get_stride()
*/
GBM_EXPORT uint32_t
gbm_bo_get_stride_for_plane(struct gbm_bo *bo, int plane)
{
return bo->gbm->v0.bo_get_stride(bo, plane);
}
/** Get the format of the buffer object
*
* The format of the pixels in the buffer.
*
* \param bo The buffer object
* \return The format of buffer object, one of the GBM_FORMAT_* codes
*/
GBM_EXPORT uint32_t
gbm_bo_get_format(struct gbm_bo *bo)
{
return bo->v0.format;
}
/** Get the bit-per-pixel of the buffer object's format
*
* The bits-per-pixel of the buffer object's format.
*
* Note; The 'in-memory pixel' concept makes no sense for YUV formats
* (pixels are the result of the combination of multiple memory sources:
* Y, Cb & Cr; usually these are even in separate buffers), so YUV
* formats are not supported by this function.
*
* \param bo The buffer object
* \return The number of bits0per-pixel of the buffer object's format.
*/
GBM_EXPORT uint32_t
gbm_bo_get_bpp(struct gbm_bo *bo)
{
switch (bo->v0.format) {
default:
return 0;
case GBM_FORMAT_C8:
case GBM_FORMAT_R8:
case GBM_FORMAT_RGB332:
case GBM_FORMAT_BGR233:
return 8;
case GBM_FORMAT_R16:
case GBM_FORMAT_GR88:
case GBM_FORMAT_XRGB4444:
case GBM_FORMAT_XBGR4444:
case GBM_FORMAT_RGBX4444:
case GBM_FORMAT_BGRX4444:
case GBM_FORMAT_ARGB4444:
case GBM_FORMAT_ABGR4444:
case GBM_FORMAT_RGBA4444:
case GBM_FORMAT_BGRA4444:
case GBM_FORMAT_XRGB1555:
case GBM_FORMAT_XBGR1555:
case GBM_FORMAT_RGBX5551:
case GBM_FORMAT_BGRX5551:
case GBM_FORMAT_ARGB1555:
case GBM_FORMAT_ABGR1555:
case GBM_FORMAT_RGBA5551:
case GBM_FORMAT_BGRA5551:
case GBM_FORMAT_RGB565:
case GBM_FORMAT_BGR565:
return 16;
case GBM_FORMAT_RGB888:
case GBM_FORMAT_BGR888:
return 24;
case GBM_FORMAT_RG1616:
case GBM_FORMAT_GR1616:
case GBM_FORMAT_XRGB8888:
case GBM_FORMAT_XBGR8888:
case GBM_FORMAT_RGBX8888:
case GBM_FORMAT_BGRX8888:
case GBM_FORMAT_ARGB8888:
case GBM_FORMAT_ABGR8888:
case GBM_FORMAT_RGBA8888:
case GBM_FORMAT_BGRA8888:
case GBM_FORMAT_XRGB2101010:
case GBM_FORMAT_XBGR2101010:
case GBM_FORMAT_RGBX1010102:
case GBM_FORMAT_BGRX1010102:
case GBM_FORMAT_ARGB2101010:
case GBM_FORMAT_ABGR2101010:
case GBM_FORMAT_RGBA1010102:
case GBM_FORMAT_BGRA1010102:
return 32;
case GBM_FORMAT_XBGR16161616:
case GBM_FORMAT_ABGR16161616:
case GBM_FORMAT_XBGR16161616F:
case GBM_FORMAT_ABGR16161616F:
return 64;
}
}
/** Get the offset for the data of the specified plane
*
* Extra planes, and even the first plane, may have an offset from the start of
* the buffer object. This function will provide the offset for the given plane
* to be used in various KMS APIs.
*
* \param bo The buffer object
* \return The offset
*/
GBM_EXPORT uint32_t
gbm_bo_get_offset(struct gbm_bo *bo, int plane)
{
return bo->gbm->v0.bo_get_offset(bo, plane);
}
/** Get the gbm device used to create the buffer object
*
* \param bo The buffer object
* \return Returns the gbm device with which the buffer object was created
*/
GBM_EXPORT struct gbm_device *
gbm_bo_get_device(struct gbm_bo *bo)
{
return bo->gbm;
}
/** Get the handle of the buffer object
*
* This is stored in the platform generic union gbm_bo_handle type. However
* the format of this handle is platform specific.
*
* \param bo The buffer object
* \return Returns the handle of the allocated buffer object
*/
GBM_EXPORT union gbm_bo_handle
gbm_bo_get_handle(struct gbm_bo *bo)
{
return bo->v0.handle;
}
/** Get a DMA-BUF file descriptor for the buffer object
*
* This function creates a DMA-BUF (also known as PRIME) file descriptor
* handle for the buffer object. Each call to gbm_bo_get_fd() returns a new
* file descriptor and the caller is responsible for closing the file
* descriptor.
* \param bo The buffer object
* \return Returns a file descriptor referring to the underlying buffer or -1
* if an error occurs.
*/
GBM_EXPORT int
gbm_bo_get_fd(struct gbm_bo *bo)
{
return bo->gbm->v0.bo_get_fd(bo);
}
/** Get the number of planes for the given bo.
*
* \param bo The buffer object
* \return The number of planes
*/
GBM_EXPORT int
gbm_bo_get_plane_count(struct gbm_bo *bo)
{
return bo->gbm->v0.bo_get_planes(bo);
}
/** Get the handle for the specified plane of the buffer object
*
* This function gets the handle for any plane associated with the BO. When
* dealing with multi-planar formats, or formats which might have implicit
* planes based on different underlying hardware it is necessary for the client
* to be able to get this information to pass to the DRM.
*
* \param bo The buffer object
* \param plane the plane to get a handle for
*
* \sa gbm_bo_get_handle()
*/
GBM_EXPORT union gbm_bo_handle
gbm_bo_get_handle_for_plane(struct gbm_bo *bo, int plane)
{
return bo->gbm->v0.bo_get_handle(bo, plane);
}
/** Get a DMA-BUF file descriptor for the specified plane of the buffer object
*
* This function creates a DMA-BUF (also known as PRIME) file descriptor
* handle for the specified plane of the buffer object. Each call to
* gbm_bo_get_fd_for_plane() returns a new file descriptor and the caller is
* responsible for closing the file descriptor.
* \param bo The buffer object
* \param plane The plane to get a DMA-BUF for
* \return Returns a file descriptor referring to the underlying buffer or -1
* if an error occurs.
*
* \sa gbm_bo_get_fd()
*/
GBM_EXPORT int
gbm_bo_get_fd_for_plane(struct gbm_bo *bo, int plane)
{
return bo->gbm->v0.bo_get_plane_fd(bo, plane);
}
/**
* Get the chosen modifier for the buffer object
*
* This function returns the modifier that was chosen for the object. These
* properties may be generic, or platform/implementation dependent.
*
* \param bo The buffer object
* \return Returns the selected modifier (chosen by the implementation) for the
* BO.
* \sa gbm_bo_create_with_modifiers() where possible modifiers are set
* \sa gbm_surface_create_with_modifiers() where possible modifiers are set
* \sa define DRM_FORMAT_MOD_* in drm_fourcc.h for possible modifiers
*/
GBM_EXPORT uint64_t
gbm_bo_get_modifier(struct gbm_bo *bo)
{
return bo->gbm->v0.bo_get_modifier(bo);
}
/** Write data into the buffer object
*
* If the buffer object was created with the GBM_BO_USE_WRITE flag,
* this function can be used to write data into the buffer object. The
* data is copied directly into the object and it's the responsibility
* of the caller to make sure the data represents valid pixel data,
* according to the width, height, stride and format of the buffer object.
*
* \param bo The buffer object
* \param buf The data to write
* \param count The number of bytes to write
* \return Returns 0 on success, otherwise -1 is returned an errno set
*/
GBM_EXPORT int
gbm_bo_write(struct gbm_bo *bo, const void *buf, size_t count)
{
return bo->gbm->v0.bo_write(bo, buf, count);
}
/** Set the user data associated with a buffer object
*
* \param bo The buffer object
* \param data The data to associate to the buffer object
* \param destroy_user_data A callback (which may be %NULL) that will be
* called prior to the buffer destruction
*/
GBM_EXPORT void
gbm_bo_set_user_data(struct gbm_bo *bo, void *data,
void (*destroy_user_data)(struct gbm_bo *, void *))
{
bo->v0.user_data = data;
bo->v0.destroy_user_data = destroy_user_data;
}
/** Get the user data associated with a buffer object
*
* \param bo The buffer object
* \return Returns the user data associated with the buffer object or %NULL
* if no data was associated with it
*
* \sa gbm_bo_set_user_data()
*/
GBM_EXPORT void *
gbm_bo_get_user_data(struct gbm_bo *bo)
{
return bo->v0.user_data;
}
/**
* Destroys the given buffer object and frees all resources associated with
* it.
*
* \param bo The buffer object
*/
GBM_EXPORT void
gbm_bo_destroy(struct gbm_bo *bo)
{
if (bo->v0.destroy_user_data)
bo->v0.destroy_user_data(bo, bo->v0.user_data);
bo->gbm->v0.bo_destroy(bo);
}
/**
* Allocate a buffer object for the given dimensions
*
* \param gbm The gbm device returned from gbm_create_device()
* \param width The width for the buffer
* \param height The height for the buffer
* \param format The format to use for the buffer, from GBM_FORMAT_* or
* GBM_BO_FORMAT_* tokens
* \param flags The union of the usage flags for this buffer
*
* \return A newly allocated buffer that should be freed with gbm_bo_destroy()
* when no longer needed. If an error occurs during allocation %NULL will be
* returned and errno set.
*
* \sa enum gbm_bo_flags for the list of usage flags
*/
GBM_EXPORT struct gbm_bo *
gbm_bo_create(struct gbm_device *gbm,
uint32_t width, uint32_t height,
uint32_t format, uint32_t flags)
{
if (width == 0 || height == 0) {
errno = EINVAL;
return NULL;
}
return gbm->v0.bo_create(gbm, width, height, format, flags, NULL, 0);
}
GBM_EXPORT struct gbm_bo *
gbm_bo_create_with_modifiers(struct gbm_device *gbm,
uint32_t width, uint32_t height,
uint32_t format,
const uint64_t *modifiers,
const unsigned int count)
{
uint32_t flags = 0;
/*
* ABI version 1 added the modifiers+flags capability. Backends from
* prior versions may fail if "unknown" flags are provided along with
* modifiers, but assume scanout is required when modifiers are used.
* Newer backends expect scanout to be explicitly requested if required,
* but applications using this older interface rely on the older implied
* requirement, so that behavior must be preserved.
*/
if (gbm->v0.backend_version >= 1) {
flags |= GBM_BO_USE_SCANOUT;
}
return gbm_bo_create_with_modifiers2(gbm, width, height, format, modifiers,
count, flags);
}
GBM_EXPORT struct gbm_bo *
gbm_bo_create_with_modifiers2(struct gbm_device *gbm,
uint32_t width, uint32_t height,
uint32_t format,
const uint64_t *modifiers,
const unsigned int count,
uint32_t flags)
{
if (width == 0 || height == 0) {
errno = EINVAL;
return NULL;
}
if ((count && !modifiers) || (modifiers && !count)) {
errno = EINVAL;
return NULL;
}
if (modifiers && (flags & GBM_BO_USE_LINEAR)) {
errno = EINVAL;
return NULL;
}
return gbm->v0.bo_create(gbm, width, height, format, flags, modifiers, count);
}
/**
* Create a gbm buffer object from a foreign object
*
* This function imports a foreign object and creates a new gbm bo for it.
* This enables using the foreign object with a display API such as KMS.
* Currently these types of foreign objects are supported, indicated by the type
* argument:
*
* GBM_BO_IMPORT_WL_BUFFER
* GBM_BO_IMPORT_EGL_IMAGE
* GBM_BO_IMPORT_FD
* GBM_BO_IMPORT_FD_MODIFIER
*
* The gbm bo shares the underlying pixels but its life-time is
* independent of the foreign object.
*
* \param gbm The gbm device returned from gbm_create_device()
* \param type The type of object we're importing
* \param buffer Pointer to the external object
* \param flags The union of the usage flags for this buffer
*
* \return A newly allocated buffer object that should be freed with
* gbm_bo_destroy() when no longer needed. On error, %NULL is returned
* and errno is set.
*
* \sa enum gbm_bo_flags for the list of usage flags
*/
GBM_EXPORT struct gbm_bo *
gbm_bo_import(struct gbm_device *gbm,
uint32_t type, void *buffer, uint32_t flags)
{
return gbm->v0.bo_import(gbm, type, buffer, flags);
}
/**
* Map a region of a gbm buffer object for cpu access
*
* This function maps a region of a gbm bo for cpu read and/or write
* access.
*
* The mapping exposes a linear view of the buffer object even if the buffer
* has a non-linear modifier.
*
* This function may require intermediate buffer copies (ie. it may be slow).
*
* \param bo The buffer object
* \param x The X (top left origin) starting position of the mapped region for
* the buffer
* \param y The Y (top left origin) starting position of the mapped region for
* the buffer
* \param width The width of the mapped region for the buffer
* \param height The height of the mapped region for the buffer
* \param flags The union of the GBM_BO_TRANSFER_* flags for this buffer
* \param stride Ptr for returned stride in bytes of the mapped region
* \param map_data Returned opaque ptr for the mapped region
*
* \return Address of the mapped buffer that should be unmapped with
* gbm_bo_unmap() when no longer needed. On error, %NULL is returned
* and errno is set.
*
* \sa enum gbm_bo_transfer_flags for the list of flags
*/
GBM_EXPORT void *
gbm_bo_map(struct gbm_bo *bo,
uint32_t x, uint32_t y,
uint32_t width, uint32_t height,
uint32_t flags, uint32_t *stride, void **map_data)
{
if (!bo || width == 0 || height == 0 || !stride || !map_data) {
errno = EINVAL;
return NULL;
}
return bo->gbm->v0.bo_map(bo, x, y, width, height,
flags, stride, map_data);
}
/**
* Unmap a previously mapped region of a gbm buffer object
*
* This function unmaps a region of a gbm bo for cpu read and/or write
* access.
*
* \param bo The buffer object
* \param map_data opaque ptr returned from prior gbm_bo_map
*/
GBM_EXPORT void
gbm_bo_unmap(struct gbm_bo *bo, void *map_data)
{
bo->gbm->v0.bo_unmap(bo, map_data);
}
/**
* Allocate a surface object
*
* \param gbm The gbm device returned from gbm_create_device()
* \param width The width for the surface
* \param height The height for the surface
* \param format The format to use for the surface
*
* \return A newly allocated surface that should be freed with
* gbm_surface_destroy() when no longer needed. If an error occurs
* during allocation %NULL will be returned.
*
* \sa enum gbm_bo_format for the list of formats
*/
GBM_EXPORT struct gbm_surface *
gbm_surface_create(struct gbm_device *gbm,
uint32_t width, uint32_t height,
uint32_t format, uint32_t flags)
{
return gbm->v0.surface_create(gbm, width, height, format, flags, NULL, 0);
}
GBM_EXPORT struct gbm_surface *
gbm_surface_create_with_modifiers(struct gbm_device *gbm,
uint32_t width, uint32_t height,
uint32_t format,
const uint64_t *modifiers,
const unsigned int count)
{
uint32_t flags = 0;
/*
* ABI version 1 added the modifiers+flags capability. Backends from
* prior versions may fail if "unknown" flags are provided along with
* modifiers, but assume scanout is required when modifiers are used.
* Newer backends expect scanout to be explicitly requested if required,
* but applications using this older interface rely on the older implied
* requirement, so that behavior must be preserved.
*/
if (gbm->v0.backend_version >= 1) {
flags |= GBM_BO_USE_SCANOUT;
}
return gbm_surface_create_with_modifiers2(gbm, width, height, format,
modifiers, count,
flags);
}
GBM_EXPORT struct gbm_surface *
gbm_surface_create_with_modifiers2(struct gbm_device *gbm,
uint32_t width, uint32_t height,
uint32_t format,
const uint64_t *modifiers,
const unsigned int count,
uint32_t flags)
{
if ((count && !modifiers) || (modifiers && !count)) {
errno = EINVAL;
return NULL;
}
if (modifiers && (flags & GBM_BO_USE_LINEAR)) {
errno = EINVAL;
return NULL;
}
return gbm->v0.surface_create(gbm, width, height, format, flags,
modifiers, count);
}
/**
* Destroys the given surface and frees all resources associated with it.
*
* Prior to calling this function all buffers locked with
* gbm_surface_lock_front_buffer() need to be released and the associated
* EGL surface destroyed.
*
* \param surf The surface
*/
GBM_EXPORT void
gbm_surface_destroy(struct gbm_surface *surf)
{
surf->gbm->v0.surface_destroy(surf);
}
/**
* Lock the surface's current front buffer
*
* Lock rendering to the surface's current front buffer until it is
* released with gbm_surface_release_buffer().
*
* This function must be called exactly once after calling
* eglSwapBuffers. Calling it before any eglSwapBuffer has happened
* on the surface or two or more times after eglSwapBuffers is an error.
*
* \param surf The surface
*
* \return A buffer object representing the front buffer that should be
* released with gbm_surface_release_buffer() when no longer needed and before
* the associated EGL surface gets destroyed. The implementation is free to
* reuse buffers released with gbm_surface_release_buffer() so this bo should
* not be destroyed using gbm_bo_destroy(). If an error occurs this function
* returns %NULL.
*/
GBM_EXPORT struct gbm_bo *
gbm_surface_lock_front_buffer(struct gbm_surface *surf)
{
return surf->gbm->v0.surface_lock_front_buffer(surf);
}
/**
* Release a locked buffer obtained with gbm_surface_lock_front_buffer()
*
* Returns the underlying buffer to the gbm surface. Releasing a bo
* will typically make gbm_surface_has_free_buffer() return 1 and thus
* allow rendering the next frame, but not always. The implementation
* may choose to destroy the bo immediately or reuse it, in which case
* the user data associated with it is unchanged.
*
* \param surf The surface
* \param bo The buffer object
*/
GBM_EXPORT void
gbm_surface_release_buffer(struct gbm_surface *surf, struct gbm_bo *bo)
{
surf->gbm->v0.surface_release_buffer(surf, bo);
}
/**
* Return whether or not a surface has free (non-locked) buffers
*
* Before starting a new frame, the surface must have a buffer
* available for rendering. Initially, a gbm surface will have a free
* buffer, but after one or more buffers have been locked (\sa
* gbm_surface_lock_front_buffer()), the application must check for a
* free buffer before rendering.
*
* If a surface doesn't have a free buffer, the application must
* return a buffer to the surface using gbm_surface_release_buffer()
* and after that, the application can query for free buffers again.
*
* \param surf The surface
* \return 1 if the surface has free buffers, 0 otherwise
*/
GBM_EXPORT int
gbm_surface_has_free_buffers(struct gbm_surface *surf)
{
return surf->gbm->v0.surface_has_free_buffers(surf);
}
/* The two GBM_BO_FORMAT_[XA]RGB8888 formats alias the GBM_FORMAT_*
* formats of the same name. We want to accept them whenever someone
* has a GBM format, but never return them to the user. */
static uint32_t
format_canonicalize(uint32_t gbm_format)
{
switch (gbm_format) {
case GBM_BO_FORMAT_XRGB8888:
return GBM_FORMAT_XRGB8888;
case GBM_BO_FORMAT_ARGB8888:
return GBM_FORMAT_ARGB8888;
default:
return gbm_format;
}
}
/**
* Returns a string representing the fourcc format name.
*
* \param desc Caller-provided storage for the format name string.
* \return String containing the fourcc of the format.
*/
GBM_EXPORT char *
gbm_format_get_name(uint32_t gbm_format, struct gbm_format_name_desc *desc)
{
gbm_format = format_canonicalize(gbm_format);
desc->name[0] = gbm_format;
desc->name[1] = gbm_format >> 8;
desc->name[2] = gbm_format >> 16;
desc->name[3] = gbm_format >> 24;
desc->name[4] = 0;
return desc->name;
}
/**
* A global table of functions and global variables defined in the core GBM
* code that need to be accessed directly by GBM backends.
*/
struct gbm_core gbm_core = {
.v0.core_version = GBM_BACKEND_ABI_VERSION,
.v0.format_canonicalize = format_canonicalize,
};

469
lib/mesa/src/gbm/main/gbm.h Normal file
View file

@ -0,0 +1,469 @@
/*
* Copyright © 2011 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Benjamin Franzke <benjaminfranzke@googlemail.com>
*/
#ifndef _GBM_H_
#define _GBM_H_
#define __GBM__ 1
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \file gbm.h
* \brief Generic Buffer Manager
*/
struct gbm_device;
struct gbm_bo;
struct gbm_surface;
/**
* \mainpage The Generic Buffer Manager
*
* This module provides an abstraction that the caller can use to request a
* buffer from the underlying memory management system for the platform.
*
* This allows the creation of portable code whilst still allowing access to
* the underlying memory manager.
*/
/**
* Abstraction representing the handle to a buffer allocated by the
* manager
*/
union gbm_bo_handle {
void *ptr;
int32_t s32;
uint32_t u32;
int64_t s64;
uint64_t u64;
};
/** Format of the allocated buffer */
enum gbm_bo_format {
/** RGB with 8 bits per channel in a 32 bit value */
GBM_BO_FORMAT_XRGB8888,
/** ARGB with 8 bits per channel in a 32 bit value */
GBM_BO_FORMAT_ARGB8888
};
/**
* The FourCC format codes are taken from the drm_fourcc.h definition, and
* re-namespaced. New GBM formats must not be added, unless they are
* identical ports from drm_fourcc.
*/
#define __gbm_fourcc_code(a,b,c,d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | \
((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
#define GBM_FORMAT_BIG_ENDIAN (1<<31) /* format is big endian instead of little endian */
/* color index */
#define GBM_FORMAT_C8 __gbm_fourcc_code('C', '8', ' ', ' ') /* [7:0] C */
/* 8 bpp Red */
#define GBM_FORMAT_R8 __gbm_fourcc_code('R', '8', ' ', ' ') /* [7:0] R */
/* 16 bpp Red */
#define GBM_FORMAT_R16 __gbm_fourcc_code('R', '1', '6', ' ') /* [15:0] R little endian */
/* 16 bpp RG */
#define GBM_FORMAT_GR88 __gbm_fourcc_code('G', 'R', '8', '8') /* [15:0] G:R 8:8 little endian */
/* 32 bpp RG */
#define GBM_FORMAT_RG1616 __gbm_fourcc_code('R', 'G', '3', '2') /* [31:0] R:G 16:16 little endian */
#define GBM_FORMAT_GR1616 __gbm_fourcc_code('G', 'R', '3', '2') /* [31:0] G:R 16:16 little endian */
/* 8 bpp RGB */
#define GBM_FORMAT_RGB332 __gbm_fourcc_code('R', 'G', 'B', '8') /* [7:0] R:G:B 3:3:2 */
#define GBM_FORMAT_BGR233 __gbm_fourcc_code('B', 'G', 'R', '8') /* [7:0] B:G:R 2:3:3 */
/* 16 bpp RGB */
#define GBM_FORMAT_XRGB4444 __gbm_fourcc_code('X', 'R', '1', '2') /* [15:0] x:R:G:B 4:4:4:4 little endian */
#define GBM_FORMAT_XBGR4444 __gbm_fourcc_code('X', 'B', '1', '2') /* [15:0] x:B:G:R 4:4:4:4 little endian */
#define GBM_FORMAT_RGBX4444 __gbm_fourcc_code('R', 'X', '1', '2') /* [15:0] R:G:B:x 4:4:4:4 little endian */
#define GBM_FORMAT_BGRX4444 __gbm_fourcc_code('B', 'X', '1', '2') /* [15:0] B:G:R:x 4:4:4:4 little endian */
#define GBM_FORMAT_ARGB4444 __gbm_fourcc_code('A', 'R', '1', '2') /* [15:0] A:R:G:B 4:4:4:4 little endian */
#define GBM_FORMAT_ABGR4444 __gbm_fourcc_code('A', 'B', '1', '2') /* [15:0] A:B:G:R 4:4:4:4 little endian */
#define GBM_FORMAT_RGBA4444 __gbm_fourcc_code('R', 'A', '1', '2') /* [15:0] R:G:B:A 4:4:4:4 little endian */
#define GBM_FORMAT_BGRA4444 __gbm_fourcc_code('B', 'A', '1', '2') /* [15:0] B:G:R:A 4:4:4:4 little endian */
#define GBM_FORMAT_XRGB1555 __gbm_fourcc_code('X', 'R', '1', '5') /* [15:0] x:R:G:B 1:5:5:5 little endian */
#define GBM_FORMAT_XBGR1555 __gbm_fourcc_code('X', 'B', '1', '5') /* [15:0] x:B:G:R 1:5:5:5 little endian */
#define GBM_FORMAT_RGBX5551 __gbm_fourcc_code('R', 'X', '1', '5') /* [15:0] R:G:B:x 5:5:5:1 little endian */
#define GBM_FORMAT_BGRX5551 __gbm_fourcc_code('B', 'X', '1', '5') /* [15:0] B:G:R:x 5:5:5:1 little endian */
#define GBM_FORMAT_ARGB1555 __gbm_fourcc_code('A', 'R', '1', '5') /* [15:0] A:R:G:B 1:5:5:5 little endian */
#define GBM_FORMAT_ABGR1555 __gbm_fourcc_code('A', 'B', '1', '5') /* [15:0] A:B:G:R 1:5:5:5 little endian */
#define GBM_FORMAT_RGBA5551 __gbm_fourcc_code('R', 'A', '1', '5') /* [15:0] R:G:B:A 5:5:5:1 little endian */
#define GBM_FORMAT_BGRA5551 __gbm_fourcc_code('B', 'A', '1', '5') /* [15:0] B:G:R:A 5:5:5:1 little endian */
#define GBM_FORMAT_RGB565 __gbm_fourcc_code('R', 'G', '1', '6') /* [15:0] R:G:B 5:6:5 little endian */
#define GBM_FORMAT_BGR565 __gbm_fourcc_code('B', 'G', '1', '6') /* [15:0] B:G:R 5:6:5 little endian */
/* 24 bpp RGB */
#define GBM_FORMAT_RGB888 __gbm_fourcc_code('R', 'G', '2', '4') /* [23:0] R:G:B little endian */
#define GBM_FORMAT_BGR888 __gbm_fourcc_code('B', 'G', '2', '4') /* [23:0] B:G:R little endian */
/* 32 bpp RGB */
#define GBM_FORMAT_XRGB8888 __gbm_fourcc_code('X', 'R', '2', '4') /* [31:0] x:R:G:B 8:8:8:8 little endian */
#define GBM_FORMAT_XBGR8888 __gbm_fourcc_code('X', 'B', '2', '4') /* [31:0] x:B:G:R 8:8:8:8 little endian */
#define GBM_FORMAT_RGBX8888 __gbm_fourcc_code('R', 'X', '2', '4') /* [31:0] R:G:B:x 8:8:8:8 little endian */
#define GBM_FORMAT_BGRX8888 __gbm_fourcc_code('B', 'X', '2', '4') /* [31:0] B:G:R:x 8:8:8:8 little endian */
#define GBM_FORMAT_ARGB8888 __gbm_fourcc_code('A', 'R', '2', '4') /* [31:0] A:R:G:B 8:8:8:8 little endian */
#define GBM_FORMAT_ABGR8888 __gbm_fourcc_code('A', 'B', '2', '4') /* [31:0] A:B:G:R 8:8:8:8 little endian */
#define GBM_FORMAT_RGBA8888 __gbm_fourcc_code('R', 'A', '2', '4') /* [31:0] R:G:B:A 8:8:8:8 little endian */
#define GBM_FORMAT_BGRA8888 __gbm_fourcc_code('B', 'A', '2', '4') /* [31:0] B:G:R:A 8:8:8:8 little endian */
#define GBM_FORMAT_XRGB2101010 __gbm_fourcc_code('X', 'R', '3', '0') /* [31:0] x:R:G:B 2:10:10:10 little endian */
#define GBM_FORMAT_XBGR2101010 __gbm_fourcc_code('X', 'B', '3', '0') /* [31:0] x:B:G:R 2:10:10:10 little endian */
#define GBM_FORMAT_RGBX1010102 __gbm_fourcc_code('R', 'X', '3', '0') /* [31:0] R:G:B:x 10:10:10:2 little endian */
#define GBM_FORMAT_BGRX1010102 __gbm_fourcc_code('B', 'X', '3', '0') /* [31:0] B:G:R:x 10:10:10:2 little endian */
#define GBM_FORMAT_ARGB2101010 __gbm_fourcc_code('A', 'R', '3', '0') /* [31:0] A:R:G:B 2:10:10:10 little endian */
#define GBM_FORMAT_ABGR2101010 __gbm_fourcc_code('A', 'B', '3', '0') /* [31:0] A:B:G:R 2:10:10:10 little endian */
#define GBM_FORMAT_RGBA1010102 __gbm_fourcc_code('R', 'A', '3', '0') /* [31:0] R:G:B:A 10:10:10:2 little endian */
#define GBM_FORMAT_BGRA1010102 __gbm_fourcc_code('B', 'A', '3', '0') /* [31:0] B:G:R:A 10:10:10:2 little endian */
/* 64 bpp RGB */
#define GBM_FORMAT_XBGR16161616 __gbm_fourcc_code('X', 'B', '4', '8') /* [63:0] x:B:G:R 16:16:16:16 little endian */
#define GBM_FORMAT_ABGR16161616 __gbm_fourcc_code('A', 'B', '4', '8') /* [63:0] A:B:G:R 16:16:16:16 little endian */
/*
* Floating point 64bpp RGB
* IEEE 754-2008 binary16 half-precision float
* [15:0] sign:exponent:mantissa 1:5:10
*/
#define GBM_FORMAT_XBGR16161616F __gbm_fourcc_code('X', 'B', '4', 'H') /* [63:0] x:B:G:R 16:16:16:16 little endian */
#define GBM_FORMAT_ABGR16161616F __gbm_fourcc_code('A', 'B', '4', 'H') /* [63:0] A:B:G:R 16:16:16:16 little endian */
/* packed YCbCr */
#define GBM_FORMAT_YUYV __gbm_fourcc_code('Y', 'U', 'Y', 'V') /* [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian */
#define GBM_FORMAT_YVYU __gbm_fourcc_code('Y', 'V', 'Y', 'U') /* [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian */
#define GBM_FORMAT_UYVY __gbm_fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */
#define GBM_FORMAT_VYUY __gbm_fourcc_code('V', 'Y', 'U', 'Y') /* [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian */
#define GBM_FORMAT_AYUV __gbm_fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */
/*
* 2 plane YCbCr
* index 0 = Y plane, [7:0] Y
* index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
* or
* index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
*/
#define GBM_FORMAT_NV12 __gbm_fourcc_code('N', 'V', '1', '2') /* 2x2 subsampled Cr:Cb plane */
#define GBM_FORMAT_NV21 __gbm_fourcc_code('N', 'V', '2', '1') /* 2x2 subsampled Cb:Cr plane */
#define GBM_FORMAT_NV16 __gbm_fourcc_code('N', 'V', '1', '6') /* 2x1 subsampled Cr:Cb plane */
#define GBM_FORMAT_NV61 __gbm_fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */
/*
* 3 plane YCbCr
* index 0: Y plane, [7:0] Y
* index 1: Cb plane, [7:0] Cb
* index 2: Cr plane, [7:0] Cr
* or
* index 1: Cr plane, [7:0] Cr
* index 2: Cb plane, [7:0] Cb
*/
#define GBM_FORMAT_YUV410 __gbm_fourcc_code('Y', 'U', 'V', '9') /* 4x4 subsampled Cb (1) and Cr (2) planes */
#define GBM_FORMAT_YVU410 __gbm_fourcc_code('Y', 'V', 'U', '9') /* 4x4 subsampled Cr (1) and Cb (2) planes */
#define GBM_FORMAT_YUV411 __gbm_fourcc_code('Y', 'U', '1', '1') /* 4x1 subsampled Cb (1) and Cr (2) planes */
#define GBM_FORMAT_YVU411 __gbm_fourcc_code('Y', 'V', '1', '1') /* 4x1 subsampled Cr (1) and Cb (2) planes */
#define GBM_FORMAT_YUV420 __gbm_fourcc_code('Y', 'U', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes */
#define GBM_FORMAT_YVU420 __gbm_fourcc_code('Y', 'V', '1', '2') /* 2x2 subsampled Cr (1) and Cb (2) planes */
#define GBM_FORMAT_YUV422 __gbm_fourcc_code('Y', 'U', '1', '6') /* 2x1 subsampled Cb (1) and Cr (2) planes */
#define GBM_FORMAT_YVU422 __gbm_fourcc_code('Y', 'V', '1', '6') /* 2x1 subsampled Cr (1) and Cb (2) planes */
#define GBM_FORMAT_YUV444 __gbm_fourcc_code('Y', 'U', '2', '4') /* non-subsampled Cb (1) and Cr (2) planes */
#define GBM_FORMAT_YVU444 __gbm_fourcc_code('Y', 'V', '2', '4') /* non-subsampled Cr (1) and Cb (2) planes */
struct gbm_format_name_desc {
char name[5];
};
/**
* Flags to indicate the intended use for the buffer - these are passed into
* gbm_bo_create(). The caller must set the union of all the flags that are
* appropriate
*
* \sa Use gbm_device_is_format_supported() to check if the combination of format
* and use flags are supported
*/
enum gbm_bo_flags {
/**
* Buffer is going to be presented to the screen using an API such as KMS
*/
GBM_BO_USE_SCANOUT = (1 << 0),
/**
* Buffer is going to be used as cursor
*/
GBM_BO_USE_CURSOR = (1 << 1),
/**
* Deprecated
*/
GBM_BO_USE_CURSOR_64X64 = GBM_BO_USE_CURSOR,
/**
* Buffer is to be used for rendering - for example it is going to be used
* as the storage for a color buffer
*/
GBM_BO_USE_RENDERING = (1 << 2),
/**
* Buffer can be used for gbm_bo_write. This is guaranteed to work
* with GBM_BO_USE_CURSOR, but may not work for other combinations.
*/
GBM_BO_USE_WRITE = (1 << 3),
/**
* Buffer is linear, i.e. not tiled.
*/
GBM_BO_USE_LINEAR = (1 << 4),
/**
* Buffer is protected, i.e. encrypted and not readable by CPU or any
* other non-secure / non-trusted components nor by non-trusted OpenGL,
* OpenCL, and Vulkan applications.
*/
GBM_BO_USE_PROTECTED = (1 << 5),
/**
* The buffer will be used for front buffer rendering. On some
* platforms this may (for example) disable framebuffer compression
* to avoid problems with compression flags data being out of sync
* with pixel data.
*/
GBM_BO_USE_FRONT_RENDERING = (1 << 6),
};
int
gbm_device_get_fd(struct gbm_device *gbm);
const char *
gbm_device_get_backend_name(struct gbm_device *gbm);
int
gbm_device_is_format_supported(struct gbm_device *gbm,
uint32_t format, uint32_t flags);
int
gbm_device_get_format_modifier_plane_count(struct gbm_device *gbm,
uint32_t format,
uint64_t modifier);
void
gbm_device_destroy(struct gbm_device *gbm);
struct gbm_device *
gbm_create_device(int fd);
struct gbm_bo *
gbm_bo_create(struct gbm_device *gbm,
uint32_t width, uint32_t height,
uint32_t format, uint32_t flags);
struct gbm_bo *
gbm_bo_create_with_modifiers(struct gbm_device *gbm,
uint32_t width, uint32_t height,
uint32_t format,
const uint64_t *modifiers,
const unsigned int count);
struct gbm_bo *
gbm_bo_create_with_modifiers2(struct gbm_device *gbm,
uint32_t width, uint32_t height,
uint32_t format,
const uint64_t *modifiers,
const unsigned int count,
uint32_t flags);
#define GBM_BO_IMPORT_WL_BUFFER 0x5501
#define GBM_BO_IMPORT_EGL_IMAGE 0x5502
#define GBM_BO_IMPORT_FD 0x5503
#define GBM_BO_IMPORT_FD_MODIFIER 0x5504
struct gbm_import_fd_data {
int fd;
uint32_t width;
uint32_t height;
uint32_t stride;
uint32_t format;
};
#define GBM_MAX_PLANES 4
struct gbm_import_fd_modifier_data {
uint32_t width;
uint32_t height;
uint32_t format;
uint32_t num_fds;
int fds[GBM_MAX_PLANES];
int strides[GBM_MAX_PLANES];
int offsets[GBM_MAX_PLANES];
uint64_t modifier;
};
struct gbm_bo *
gbm_bo_import(struct gbm_device *gbm, uint32_t type,
void *buffer, uint32_t flags);
/**
* Flags to indicate the type of mapping for the buffer - these are
* passed into gbm_bo_map(). The caller must set the union of all the
* flags that are appropriate.
*
* These flags are independent of the GBM_BO_USE_* creation flags. However,
* mapping the buffer may require copying to/from a staging buffer.
*
* See also: pipe_map_flags
*/
enum gbm_bo_transfer_flags {
/**
* Buffer contents read back (or accessed directly) at transfer
* create time.
*/
GBM_BO_TRANSFER_READ = (1 << 0),
/**
* Buffer contents will be written back at unmap time
* (or modified as a result of being accessed directly).
*/
GBM_BO_TRANSFER_WRITE = (1 << 1),
/**
* Read/modify/write
*/
GBM_BO_TRANSFER_READ_WRITE = (GBM_BO_TRANSFER_READ | GBM_BO_TRANSFER_WRITE),
};
void *
gbm_bo_map(struct gbm_bo *bo,
uint32_t x, uint32_t y, uint32_t width, uint32_t height,
uint32_t flags, uint32_t *stride, void **map_data);
void
gbm_bo_unmap(struct gbm_bo *bo, void *map_data);
uint32_t
gbm_bo_get_width(struct gbm_bo *bo);
uint32_t
gbm_bo_get_height(struct gbm_bo *bo);
uint32_t
gbm_bo_get_stride(struct gbm_bo *bo);
uint32_t
gbm_bo_get_stride_for_plane(struct gbm_bo *bo, int plane);
uint32_t
gbm_bo_get_format(struct gbm_bo *bo);
uint32_t
gbm_bo_get_bpp(struct gbm_bo *bo);
uint32_t
gbm_bo_get_offset(struct gbm_bo *bo, int plane);
struct gbm_device *
gbm_bo_get_device(struct gbm_bo *bo);
union gbm_bo_handle
gbm_bo_get_handle(struct gbm_bo *bo);
int
gbm_bo_get_fd(struct gbm_bo *bo);
uint64_t
gbm_bo_get_modifier(struct gbm_bo *bo);
int
gbm_bo_get_plane_count(struct gbm_bo *bo);
union gbm_bo_handle
gbm_bo_get_handle_for_plane(struct gbm_bo *bo, int plane);
int
gbm_bo_get_fd_for_plane(struct gbm_bo *bo, int plane);
int
gbm_bo_write(struct gbm_bo *bo, const void *buf, size_t count);
void
gbm_bo_set_user_data(struct gbm_bo *bo, void *data,
void (*destroy_user_data)(struct gbm_bo *, void *));
void *
gbm_bo_get_user_data(struct gbm_bo *bo);
void
gbm_bo_destroy(struct gbm_bo *bo);
struct gbm_surface *
gbm_surface_create(struct gbm_device *gbm,
uint32_t width, uint32_t height,
uint32_t format, uint32_t flags);
struct gbm_surface *
gbm_surface_create_with_modifiers(struct gbm_device *gbm,
uint32_t width, uint32_t height,
uint32_t format,
const uint64_t *modifiers,
const unsigned int count);
struct gbm_surface *
gbm_surface_create_with_modifiers2(struct gbm_device *gbm,
uint32_t width, uint32_t height,
uint32_t format,
const uint64_t *modifiers,
const unsigned int count,
uint32_t flags);
struct gbm_bo *
gbm_surface_lock_front_buffer(struct gbm_surface *surface);
void
gbm_surface_release_buffer(struct gbm_surface *surface, struct gbm_bo *bo);
int
gbm_surface_has_free_buffers(struct gbm_surface *surface);
void
gbm_surface_destroy(struct gbm_surface *surface);
char *
gbm_format_get_name(uint32_t gbm_format, struct gbm_format_name_desc *desc);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,426 @@
/*
* Copyright © 2021 NVIDIA Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "gbm_backend_abi.h" /* Current GBM backend ABI implementation */
#include <stddef.h> /* offsetof */
#include <stdio.h> /* printf */
/*
* The following are previous implementations of the structures defined in
* gbm_backend_abi.h, with their ABI version appended.
*
* DO NOT EVER CHANGE EXISTING DEFINITIONS HERE!
*
* Changing them implies breaking the GBM backend ABI. Instead, to extend the
* ABI, in gbm_backend_abi.h:
*
* -Add a new versioned struct
* -Append it to the associated top-level object's struct
* -Increment GBM_BACKEND_ABI_VERSION
*
* Then, here:
*
* -Add a new block of definitions below for the new ABI content
* -Add a new block of checks in main()
*/
/*
* From: Simon Ser - "gbm: assume USE_SCANOUT in create_with_modifiers"
*
* Note: ABI 1 is identical to ABI 0, except gbm_device_v0.bo_create can
* provide both modifiers and usage.
*/
#define GBM_BACKEND_ABI_VERSION_abi0 1
struct gbm_device_v0_abi0 {
const struct gbm_backend_desc *backend_desc;
uint32_t backend_version;
int fd;
const char *name;
void (*destroy)(struct gbm_device *gbm);
int (*is_format_supported)(struct gbm_device *gbm,
uint32_t format,
uint32_t usage);
int (*get_format_modifier_plane_count)(struct gbm_device *device,
uint32_t format,
uint64_t modifier);
struct gbm_bo *(*bo_create)(struct gbm_device *gbm,
uint32_t width, uint32_t height,
uint32_t format,
uint32_t usage,
const uint64_t *modifiers,
const unsigned int count);
struct gbm_bo *(*bo_import)(struct gbm_device *gbm, uint32_t type,
void *buffer, uint32_t usage);
void *(*bo_map)(struct gbm_bo *bo,
uint32_t x, uint32_t y,
uint32_t width, uint32_t height,
uint32_t flags, uint32_t *stride,
void **map_data);
void (*bo_unmap)(struct gbm_bo *bo, void *map_data);
int (*bo_write)(struct gbm_bo *bo, const void *buf, size_t data);
int (*bo_get_fd)(struct gbm_bo *bo);
int (*bo_get_planes)(struct gbm_bo *bo);
union gbm_bo_handle (*bo_get_handle)(struct gbm_bo *bo, int plane);
int (*bo_get_plane_fd)(struct gbm_bo *bo, int plane);
uint32_t (*bo_get_stride)(struct gbm_bo *bo, int plane);
uint32_t (*bo_get_offset)(struct gbm_bo *bo, int plane);
uint64_t (*bo_get_modifier)(struct gbm_bo *bo);
void (*bo_destroy)(struct gbm_bo *bo);
struct gbm_surface *(*surface_create)(struct gbm_device *gbm,
uint32_t width, uint32_t height,
uint32_t format, uint32_t flags,
const uint64_t *modifiers,
const unsigned count);
struct gbm_bo *(*surface_lock_front_buffer)(struct gbm_surface *surface);
void (*surface_release_buffer)(struct gbm_surface *surface,
struct gbm_bo *bo);
int (*surface_has_free_buffers)(struct gbm_surface *surface);
void (*surface_destroy)(struct gbm_surface *surface);
};
struct gbm_device_abi0 {
/* Hack to make a gbm_device detectable by its first element. */
struct gbm_device *(*dummy)(int);
struct gbm_device_v0_abi0 v0;
};
/**
* GBM buffer object interface corresponding to GBM_BACKEND_ABI_VERSION = 0
*
* DO NOT MODIFY THIS STRUCT. Instead, introduce a gbm_bo_v1, increment
* GBM_BACKEND_ABI_VERSION, and append gbm_bo_v1 to gbm_bo.
*/
struct gbm_bo_v0_abi0 {
uint32_t width;
uint32_t height;
uint32_t stride;
uint32_t format;
union gbm_bo_handle handle;
void *user_data;
void (*destroy_user_data)(struct gbm_bo *, void *);
};
/**
* The allocated buffer object.
*
* The members in this structure should not be accessed directly.
*
* To modify this structure, introduce a new gbm_bo_v<N> structure, add it to
* the end of this structure, and increment GBM_BACKEND_ABI_VERSION.
*/
struct gbm_bo_abi0 {
struct gbm_device *gbm;
struct gbm_bo_v0_abi0 v0;
};
/**
* GBM surface interface corresponding to GBM_BACKEND_ABI_VERSION = 0
*
* DO NOT MODIFY THIS STRUCT. Instead, introduce a gbm_surface_v1, increment
* GBM_BACKEND_ABI_VERSION, and append gbm_surface_v1 to gbm_surface.
*/
struct gbm_surface_v0_abi0 {
uint32_t width;
uint32_t height;
uint32_t format;
uint32_t flags;
struct {
uint64_t *modifiers;
unsigned count;
};
};
/**
* An allocated GBM surface.
*
* To modify this structure, introduce a new gbm_surface_v<N> structure, add it
* to the end of this structure, and increment GBM_BACKEND_ABI_VERSION.
*/
struct gbm_surface_abi0 {
struct gbm_device *gbm;
struct gbm_surface_v0_abi0 v0;
};
/**
* GBM backend interfaces corresponding to GBM_BACKEND_ABI_VERSION = 0
*
* DO NOT MODIFY THIS STRUCT. Instead, introduce a gbm_backend_v1, increment
* GBM_BACKEND_ABI_VERSION, append gbm_backend_v1 to gbm_backend.
*/
struct gbm_backend_v0_abi0 {
/**
* The version of the GBM backend interface supported by this backend. This
* is set by the backend itself, and may be greater or less than the version
* supported by the loader. It is the responsibility of the GBM loader to
* respect this version when accessing fields in this structure.
*/
uint32_t backend_version;
const char *backend_name;
struct gbm_device *(*create_device)(int fd, uint32_t gbm_backend_version);
};
/**
* The interface exposed by an external GBM backend.
*
* To modify this structure, introduce a new gbm_backend_v<N> structure, add it
* to the end of this structure, and increment GBM_BACKEND_ABI_VERSION.
*/
struct gbm_backend_abi0 {
struct gbm_backend_v0_abi0 v0;
};
/**
* GBM interfaces exposed to GBM backends at GBM_BACKEND_ABI_VERSION >= 0
*
* DO NOT MODIFY THIS STRUCT. Instead, introduce a gbm_core_v1, increment
* GBM_BACKEND_ABI_VERSION, and append gbm_core_v1 to gbm_backend.
*/
struct gbm_core_v0_abi0 {
/**
* The version of the GBM backend interface supported by the GBM loader. This
* is set by the loader, and may be greater or less than the version
* supported by a given backend. It is the responsibility of the backend to
* respect this version when accessing fields in this structure and other
* structures allocated or modified by the loader.
*/
uint32_t core_version;
uint32_t (*format_canonicalize)(uint32_t gbm_format);
};
/**
* The interface exposed by the GBM core/loader code to GBM backends.
*
* To modify this structure, introduce a new gbm_core_v<N> structure, add it
* to the end of this structure, and increment GBM_BACKEND_ABI_VERSION.
*/
struct gbm_core_abi0 {
struct gbm_core_v0_abi0 v0;
};
typedef const struct gbm_backend *(*GBM_GET_BACKEND_PROC_PTR_abi0)(const struct gbm_core *gbm_core);
/*
* Structure/member ABI-checking helper macros
*/
#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
#define CHECK_RENAMED_MEMBER_BASE(type, a_ver, b_ver, a_member, b_member) \
do { \
if (offsetof(struct type ## a_ver, a_member) != \
offsetof(struct type ## b_ver, b_member)) { \
printf("Backards incompatible change detected!\n " \
"offsetof(struct " #type #a_ver "::" #a_member ") != " \
"offsetof(struct " #type #b_ver "::" #b_member ")\n"); \
return 1; \
} \
\
if (MEMBER_SIZE(struct type ## a_ver, a_member) != \
MEMBER_SIZE(struct type ## b_ver, b_member)) { \
printf("Backards incompatible change detected!\n " \
"MEMBER_SIZE(struct " #type #a_ver "::" #a_member ") != " \
"MEMBER_SIZE(struct " #type #b_ver "::" #b_member ")\n"); \
return 1; \
} \
} while (0)
#define CHECK_RENAMED_MEMBER_TYPE(type, a_ver, b_ver, a_member, b_member) \
do { \
/* Compile-time type compatibility check */ \
struct type ## a_ver a; \
struct type ## b_ver b = {0}; \
a.a_member = b.b_member; \
(void)a; \
} while (0)
#define CHECK_RENAMED_MEMBER(type, a_ver, b_ver, a_member, b_member) \
do { \
CHECK_RENAMED_MEMBER_BASE(type, a_ver, b_ver, a_member, b_member); \
CHECK_RENAMED_MEMBER_TYPE(type, a_ver, b_ver, a_member, b_member); \
} while (0)
#define CHECK_RENAMED_MEMBER_NO_TYPE(type, a_ver, b_ver, a_member, b_member) \
CHECK_RENAMED_MEMBER_BASE(type, a_ver, b_ver, a_member, b_member);
#define CHECK_MEMBER(type, a_ver, b_ver, member) \
CHECK_RENAMED_MEMBER(type, a_ver, b_ver, member, member)
#define CHECK_MEMBER_NO_TYPE(type, a_ver, b_ver, member) \
CHECK_RENAMED_MEMBER_NO_TYPE(type, a_ver, b_ver, member, member)
#define CHECK_MEMBER_CURRENT(type, a_ver, member) \
CHECK_MEMBER(type, a_ver,, member)
#define CHECK_MEMBER_CURRENT_NO_TYPE(type, a_ver, member) \
CHECK_MEMBER_NO_TYPE(type, a_ver,, member)
#define CHECK_SIZE(type, a_ver, b_ver) \
do { \
if (sizeof(struct type ## a_ver) > \
sizeof(struct type ## b_ver)) { \
printf("Backards incompatible change detected!\n " \
"sizeof(struct " #type #a_ver ") > " \
"sizeof(struct " #type #b_ver ")\n"); \
return 1; \
} \
} while (0)
#define CHECK_SIZE_CURRENT(type, a_ver) \
do { \
if (sizeof(struct type ## a_ver) != \
sizeof(struct type)) { \
printf("Backards incompatible change detected!\n " \
"sizeof(struct " #type #a_ver ") != " \
"sizeof(struct " #type ")\n"); \
return 1; \
} \
} while (0)
#define CHECK_VERSION(a_ver, b_ver) \
do { \
if ((GBM_BACKEND_ABI_VERSION ## a_ver) >= \
(GBM_BACKEND_ABI_VERSION ## b_ver)) { \
printf("Backards incompatible change detected!\n " \
"GBM_BACKEND_ABI_VERSION" #a_ver " >= " \
"GBM_BACKEND_ABI_VERSION" #b_ver "\n"); \
return 1; \
} \
} while (0)
#define CHECK_VERSION_CURRENT(a_ver) \
do { \
if ((GBM_BACKEND_ABI_VERSION ## a_ver) != \
(GBM_BACKEND_ABI_VERSION)) { \
printf("Backards incompatible change detected!\n " \
"GBM_BACKEND_ABI_VERSION" #a_ver " != " \
"GBM_BACKEND_ABI_VERSION\n"); \
return 1; \
} \
} while (0)
#define CHECK_PROC(proc, a_ver, b_ver) \
do { \
proc ## a_ver a; \
proc ## b_ver b = NULL; \
a = b; \
(void)a; \
} while (0)
#define CHECK_PROC_CURRENT(proc, a_ver) \
CHECK_PROC(proc, a_ver,)
int main(int argc, char **argv)
{
/********************************************/
/*** Compare Current ABI to ABI version 0 ***/
/********************************************/
/* Check current gbm_device ABI against gbm_device_abi0*/
CHECK_MEMBER_CURRENT(gbm_device, _abi0, dummy);
CHECK_MEMBER_CURRENT_NO_TYPE(gbm_device, _abi0, v0);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, backend_desc);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, backend_version);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, fd);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, name);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, destroy);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, is_format_supported);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, get_format_modifier_plane_count);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_create);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_import);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_map);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_unmap);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_write);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_get_fd);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_get_planes);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_get_handle);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_get_plane_fd);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_get_stride);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_get_offset);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_get_modifier);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_destroy);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, surface_create);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, surface_lock_front_buffer);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, surface_release_buffer);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, surface_has_free_buffers);
CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, surface_destroy);
/* Size of ABI-versioned substructures verified by above member checks */
CHECK_SIZE_CURRENT (gbm_device, _abi0);
/* Check current gbm_bo ABI against gbm_bo_abi0*/
CHECK_MEMBER_CURRENT(gbm_bo, _abi0, gbm);
CHECK_MEMBER_CURRENT_NO_TYPE(gbm_bo, _abi0, v0);
CHECK_MEMBER_CURRENT(gbm_bo_v0, _abi0, width);
CHECK_MEMBER_CURRENT(gbm_bo_v0, _abi0, height);
CHECK_MEMBER_CURRENT(gbm_bo_v0, _abi0, stride);
CHECK_MEMBER_CURRENT(gbm_bo_v0, _abi0, format);
CHECK_MEMBER_CURRENT(gbm_bo_v0, _abi0, handle);
CHECK_MEMBER_CURRENT(gbm_bo_v0, _abi0, user_data);
CHECK_MEMBER_CURRENT(gbm_bo_v0, _abi0, destroy_user_data);
/* Size of ABI-versioned substructures verified by above member checks */
CHECK_SIZE_CURRENT (gbm_bo, _abi0);
/* Check current gbm_surface ABI against gbm_surface_abi0 */
CHECK_MEMBER_CURRENT(gbm_surface, _abi0, gbm);
CHECK_MEMBER_CURRENT_NO_TYPE(gbm_surface, _abi0, v0);
CHECK_MEMBER_CURRENT(gbm_surface_v0, _abi0, width);
CHECK_MEMBER_CURRENT(gbm_surface_v0, _abi0, height);
CHECK_MEMBER_CURRENT(gbm_surface_v0, _abi0, format);
CHECK_MEMBER_CURRENT(gbm_surface_v0, _abi0, flags);
CHECK_MEMBER_CURRENT(gbm_surface_v0, _abi0, modifiers);
CHECK_MEMBER_CURRENT(gbm_surface_v0, _abi0, count);
/* Size of ABI-versioned substructures verified by above member checks */
CHECK_SIZE_CURRENT (gbm_surface, _abi0);
/* Check current gbm_backend ABI against gbm_backend_abi0 */
CHECK_MEMBER_CURRENT_NO_TYPE(gbm_backend, _abi0, v0);
CHECK_MEMBER_CURRENT(gbm_backend_v0, _abi0, backend_version);
CHECK_MEMBER_CURRENT(gbm_backend_v0, _abi0, backend_name);
CHECK_MEMBER_CURRENT(gbm_backend_v0, _abi0, create_device);
/* Size of ABI-versioned substructures verified by above member checks */
CHECK_SIZE_CURRENT (gbm_backend, _abi0);
/* Check current gbm_core ABI against gbm_core_abi0 */
CHECK_MEMBER_CURRENT_NO_TYPE(gbm_core, _abi0, v0);
CHECK_MEMBER_CURRENT(gbm_core_v0, _abi0, core_version);
CHECK_MEMBER_CURRENT(gbm_core_v0, _abi0, format_canonicalize);
/* Size of ABI-versioned substructures verified by above member checks */
CHECK_SIZE_CURRENT (gbm_core, _abi0);
CHECK_PROC_CURRENT (GBM_GET_BACKEND_PROC_PTR, _abi0);
return 0;
}

View file

@ -0,0 +1,305 @@
/*
* Copyright © 2011 Intel Corporation
* Copyright © 2021 NVIDIA Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Benjamin Franzke <benjaminfranzke@googlemail.com>
* James Jones <jajones@nvidia.com>
*/
#ifndef GBM_BACKEND_ABI_H_
#define GBM_BACKEND_ABI_H_
#include "gbm.h"
/**
* \file gbm_backend_abi.h
* \brief ABI between the GBM loader and its backends
*/
struct gbm_backend_desc;
/**
* The GBM backend interface version defined by this file.
*
* The GBM device interface version must be incremented whenever the structures
* defined in this file are modified. To preserve ABI compatibility with
* backends that support only older versions, modifications to this file must
* consist only of appending new fields to the end of the structures defined in
* it, defining new structures, or declaring new exported functions or global
* variables.
*
* Note this version applies to ALL structures in this file, not just the core,
* backend, and device structures which contain it explicitly. Buffer objects,
* surfaces, and any other new structures introduced to this file are also part
* of the backend ABI. The ABI version of an instance of any object in this file
* is defined as the minimum of the version of the backend associated with the
* object instance and the loader's core object version. Hence, any new objects
* added to this file should contain either a reference to an existing object
* defined here, or an explicit version field.
*
* A few examples of object versions:
*
* Backend ABI version: 0
* Core ABI version: 3
* ABI version of a device created by the backend: 0
*
* Backend ABI version: 2
* Core ABI version: 1
* ABI version of a surface created by a device from the backend: 1
*
* Backend ABI version: 4
* Core ABI version: 4
* ABI version of a buffer object created by a device from the backend: 4
*/
#define GBM_BACKEND_ABI_VERSION 1
/**
* GBM device interface corresponding to GBM_BACKEND_ABI_VERSION = 0
*
* DO NOT MODIFY THIS STRUCT. Instead, introduce a gbm_bo_v1, increment
* GBM_BACKEND_ABI_VERSION, and append gbm_bo_v1 to gbm_bo.
*/
struct gbm_device_v0 {
const struct gbm_backend_desc *backend_desc;
/**
* The version of the GBM backend interface supported by this device and its
* child objects. This may be less than the maximum version supported by the
* GBM loader if the device was created by an older backend, or less than the
* maximum version supported by the backend if the device was created by an
* older loader. In other words, this will be:
*
* MIN(backend GBM interface version, loader GBM interface version)
*
* It is the backend's responsibility to assign this field the value passed
* in by the GBM loader to the backend's create_device function. The GBM
* loader will pre-clamp the value based on the loader version and the
* version reported by the backend in its gbm_backend_v0::backend_version
* field. It is the loader's responsibility to respect this version when
* directly accessing a device instance or any child objects instantiated by
* a device instance.
*/
uint32_t backend_version;
int fd;
const char *name;
void (*destroy)(struct gbm_device *gbm);
int (*is_format_supported)(struct gbm_device *gbm,
uint32_t format,
uint32_t usage);
int (*get_format_modifier_plane_count)(struct gbm_device *device,
uint32_t format,
uint64_t modifier);
/**
* Since version 1, usage is properly populated when modifiers are
* supplied. Version 0 always set usage to 0 in this case.
*/
struct gbm_bo *(*bo_create)(struct gbm_device *gbm,
uint32_t width, uint32_t height,
uint32_t format,
uint32_t usage,
const uint64_t *modifiers,
const unsigned int count);
struct gbm_bo *(*bo_import)(struct gbm_device *gbm, uint32_t type,
void *buffer, uint32_t usage);
void *(*bo_map)(struct gbm_bo *bo,
uint32_t x, uint32_t y,
uint32_t width, uint32_t height,
uint32_t flags, uint32_t *stride,
void **map_data);
void (*bo_unmap)(struct gbm_bo *bo, void *map_data);
int (*bo_write)(struct gbm_bo *bo, const void *buf, size_t data);
int (*bo_get_fd)(struct gbm_bo *bo);
int (*bo_get_planes)(struct gbm_bo *bo);
union gbm_bo_handle (*bo_get_handle)(struct gbm_bo *bo, int plane);
int (*bo_get_plane_fd)(struct gbm_bo *bo, int plane);
uint32_t (*bo_get_stride)(struct gbm_bo *bo, int plane);
uint32_t (*bo_get_offset)(struct gbm_bo *bo, int plane);
uint64_t (*bo_get_modifier)(struct gbm_bo *bo);
void (*bo_destroy)(struct gbm_bo *bo);
/**
* Since version 1, flags are properly populated when modifiers are
* supplied. Version 0 always set flags to 0 in this case.
*/
struct gbm_surface *(*surface_create)(struct gbm_device *gbm,
uint32_t width, uint32_t height,
uint32_t format, uint32_t flags,
const uint64_t *modifiers,
const unsigned count);
struct gbm_bo *(*surface_lock_front_buffer)(struct gbm_surface *surface);
void (*surface_release_buffer)(struct gbm_surface *surface,
struct gbm_bo *bo);
int (*surface_has_free_buffers)(struct gbm_surface *surface);
void (*surface_destroy)(struct gbm_surface *surface);
};
/**
* The device used for the memory allocation.
*
* The members of this structure should be not accessed directly
*
* To modify this structure, introduce a new gbm_device_v<N> structure, add it
* to the end of this structure, and increment GBM_BACKEND_ABI_VERSION.
*/
struct gbm_device {
/* Hack to make a gbm_device detectable by its first element. */
struct gbm_device *(*dummy)(int);
struct gbm_device_v0 v0;
};
/**
* GBM buffer object interface corresponding to GBM_BACKEND_ABI_VERSION = 0
*
* DO NOT MODIFY THIS STRUCT. Instead, introduce a gbm_bo_v1, increment
* GBM_BACKEND_ABI_VERSION, and append gbm_bo_v1 to gbm_bo.
*/
struct gbm_bo_v0 {
uint32_t width;
uint32_t height;
uint32_t stride;
uint32_t format;
union gbm_bo_handle handle;
void *user_data;
void (*destroy_user_data)(struct gbm_bo *, void *);
};
/**
* The allocated buffer object.
*
* The members in this structure should not be accessed directly.
*
* To modify this structure, introduce a new gbm_bo_v<N> structure, add it to
* the end of this structure, and increment GBM_BACKEND_ABI_VERSION.
*/
struct gbm_bo {
struct gbm_device *gbm;
struct gbm_bo_v0 v0;
};
/**
* GBM surface interface corresponding to GBM_BACKEND_ABI_VERSION = 0
*
* DO NOT MODIFY THIS STRUCT. Instead, introduce a gbm_surface_v1, increment
* GBM_BACKEND_ABI_VERSION, and append gbm_surface_v1 to gbm_surface.
*/
struct gbm_surface_v0 {
uint32_t width;
uint32_t height;
uint32_t format;
uint32_t flags;
struct {
uint64_t *modifiers;
unsigned count;
};
};
/**
* An allocated GBM surface.
*
* To modify this structure, introduce a new gbm_surface_v<N> structure, add it
* to the end of this structure, and increment GBM_BACKEND_ABI_VERSION.
*/
struct gbm_surface {
struct gbm_device *gbm;
struct gbm_surface_v0 v0;
};
/**
* GBM backend interfaces corresponding to GBM_BACKEND_ABI_VERSION = 0
*
* DO NOT MODIFY THIS STRUCT. Instead, introduce a gbm_backend_v1, increment
* GBM_BACKEND_ABI_VERSION, append gbm_backend_v1 to gbm_backend.
*/
struct gbm_backend_v0 {
/**
* The version of the GBM backend interface supported by this backend. This
* is set by the backend itself, and may be greater or less than the version
* supported by the loader. It is the responsibility of the GBM loader to
* respect this version when accessing fields in this structure.
*/
uint32_t backend_version;
const char *backend_name;
struct gbm_device *(*create_device)(int fd, uint32_t gbm_backend_version);
};
/**
* The interface exposed by an external GBM backend.
*
* To modify this structure, introduce a new gbm_backend_v<N> structure, add it
* to the end of this structure, and increment GBM_BACKEND_ABI_VERSION.
*/
struct gbm_backend {
struct gbm_backend_v0 v0;
};
/**
* GBM interfaces exposed to GBM backends at GBM_BACKEND_ABI_VERSION >= 0
*
* DO NOT MODIFY THIS STRUCT. Instead, introduce a gbm_core_v1, increment
* GBM_BACKEND_ABI_VERSION, and append gbm_core_v1 to gbm_backend.
*/
struct gbm_core_v0 {
/**
* The version of the GBM backend interface supported by the GBM loader. This
* is set by the loader, and may be greater or less than the version
* supported by a given backend. It is the responsibility of the backend to
* respect this version when accessing fields in this structure and other
* structures allocated or modified by the loader.
*/
uint32_t core_version;
uint32_t (*format_canonicalize)(uint32_t gbm_format);
};
/**
* The interface exposed by the GBM core/loader code to GBM backends.
*
* To modify this structure, introduce a new gbm_core_v<N> structure, add it
* to the end of this structure, and increment GBM_BACKEND_ABI_VERSION.
*/
struct gbm_core {
struct gbm_core_v0 v0;
};
/**
* The entrypoint an external GBM backend exports.
*
* Prior to creating any devices using the backend, GBM will look up and call
* this function to request the backend's interface and convey the loader's
* version and exported interface to the backend.
*
* DO NOT MODIFY THIS FUNCTION NAME OR PROTOTYPE. It must remain unchanged to
* preserve backwards compatibility with existing GBM backends.
*/
#define GBM_GET_BACKEND_PROC gbmint_get_backend
#define _GBM_MKSTRX(s) _GBM_MKSTR(s)
#define _GBM_MKSTR(s) #s
#define GBM_GET_BACKEND_PROC_NAME _GBM_MKSTRX(GBM_GET_BACKEND_PROC)
typedef const struct gbm_backend *(*GBM_GET_BACKEND_PROC_PTR)(const struct gbm_core *gbm_core);
#endif

View file

@ -0,0 +1,49 @@
/*
* Copyright © 2011 Intel Corporation
* Copyright © 2021 NVIDIA Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Benjamin Franzke <benjaminfranzke@googlemail.com>
* James Jones <jajones@nvidia.com>
*/
#ifndef INTERNAL_H_
#define INTERNAL_H_
#include "gbm_backend_abi.h"
/* GCC visibility */
#if defined(__GNUC__)
#define GBM_EXPORT __attribute__ ((visibility("default")))
#else
#define GBM_EXPORT
#endif
/**
* \file gbmint.h
* \brief Internal implementation details of gbm
*/
extern struct gbm_core gbm_core;
#endif

View file

@ -0,0 +1,95 @@
# Copyright © 2017 Intel Corporation
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
inc_gbm = include_directories('.', 'main', 'backends/dri')
files_gbm = files(
'main/backend.c',
'main/backend.h',
'main/gbm.c',
'main/gbm.h',
'main/gbmint.h',
)
deps_gbm = []
args_gbm = [
'-DDEFAULT_BACKENDS_PATH="@0@"'.format(gbm_backends_path),
]
deps_gbm = []
incs_gbm = [
include_directories('main'), inc_include, inc_src, inc_loader,
]
if with_dri2
files_gbm += files('backends/dri/gbm_dri.c', 'backends/dri/gbm_driint.h')
deps_gbm += dep_libdrm # TODO: pthread-stubs
endif
if with_platform_wayland
deps_gbm += dep_wayland_server
incs_gbm += inc_wayland_drm
endif
libgbm_name = 'gbm'
if with_platform_android and get_option('platform-sdk-version') >= 30
libgbm_name = 'gbm_mesa'
endif
libgbm = shared_library(
libgbm_name,
files_gbm,
include_directories : incs_gbm,
c_args : [args_gbm],
link_args : [ld_args_gc_sections],
link_with : libloader,
dependencies : [deps_gbm, dep_dl, dep_thread, idep_mesautil, idep_xmlconfig],
gnu_symbol_visibility : 'hidden',
version : '1.0.0',
install : true,
)
if with_tests
abi_check = executable('gbm_abi_check', 'main/gbm_abi_check.c')
test('gbm-abi-check', abi_check, suite : ['gbm'])
endif
install_headers('main/gbm.h')
pkg.generate(
name : 'gbm',
filebase : 'gbm',
description : 'Mesa gbm library',
version : meson.project_version(),
libraries : libgbm,
libraries_private : gbm_priv_libs,
variables : ['gbmbackendspath=' + gbm_backends_path],
)
if with_symbols_check
test(
'gbm-symbols-check',
symbols_check,
args : [
'--lib', libgbm,
'--symbols-file', files('gbm-symbols.txt'),
symbols_check_args,
],
suite : ['gbm'],
)
endif