Skip to content
Commits on Source (24)
......@@ -98,7 +98,7 @@ drm_fb_addfb(struct drm_backend *b, struct drm_fb *fb)
/* Legacy AddFB can't always infer the format from depth/bpp alone, so
* check if our format is one of the lucky ones. */
if (!fb->format->depth || !fb->format->bpp)
if (!fb->format->addfb_legacy_depth || !fb->format->bpp)
return ret;
/* Cannot fall back to AddFB for multi-planar formats either. */
......@@ -106,7 +106,7 @@ drm_fb_addfb(struct drm_backend *b, struct drm_fb *fb)
return ret;
ret = drmModeAddFB(fb->fd, fb->width, fb->height,
fb->format->depth, fb->format->bpp,
fb->format->addfb_legacy_depth, fb->format->bpp,
fb->strides[0], fb->handles[0], &fb->fb_id);
return ret;
}
......@@ -134,7 +134,7 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int height,
goto err_fb;
}
if (!fb->format->depth || !fb->format->bpp) {
if (!fb->format->addfb_legacy_depth || !fb->format->bpp) {
weston_log("format 0x%lx is not compatible with dumb buffers\n",
(unsigned long) format);
goto err_fb;
......
......@@ -2439,7 +2439,7 @@ weston_buffer_from_resource(struct weston_compositor *ec,
pixel_format_get_info_shm(wl_shm_buffer_get_format(shm));
buffer->format_modifier = DRM_FORMAT_MOD_LINEAR;
if (!buffer->pixel_format)
if (!buffer->pixel_format || buffer->pixel_format->hide_from_clients)
goto fail;
} else if ((dmabuf = linux_dmabuf_buffer_get(buffer->resource))) {
buffer->type = WESTON_BUFFER_DMABUF;
......@@ -2451,7 +2451,7 @@ weston_buffer_from_resource(struct weston_compositor *ec,
pixel_format_get_info(dmabuf->attributes.format);
/* dmabuf import should assure we don't create a buffer with an
* unknown format */
assert(buffer->pixel_format);
assert(buffer->pixel_format && !buffer->pixel_format->hide_from_clients);
buffer->format_modifier = dmabuf->attributes.modifier[0];
if (dmabuf->attributes.flags & ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT)
buffer->buffer_origin = ORIGIN_BOTTOM_LEFT;
......
......@@ -48,6 +48,7 @@
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <GLES3/gl3.h>
#define GL_FORMAT(fmt) .gl_format = (fmt)
#define GL_TYPE(type) .gl_type = (type)
#define SAMPLER_TYPE(type) .sampler_type = (type)
......@@ -81,27 +82,48 @@
* colour channels, are not supported.
*/
static const struct pixel_format_info pixel_format_table[] = {
{
DRM_FORMAT(R8),
BITS_RGBA_FIXED(8, 0, 0, 0),
.bpp = 8,
.hide_from_clients = true,
GL_FORMAT(GL_R8_EXT),
GL_TYPE(GL_UNSIGNED_BYTE),
},
{
DRM_FORMAT(GR88),
BITS_RGBA_FIXED(8, 8, 0, 0),
.bpp = 16,
.hide_from_clients = true,
GL_FORMAT(GL_RG8_EXT),
GL_TYPE(GL_UNSIGNED_BYTE),
},
{
DRM_FORMAT(XRGB4444),
BITS_RGBA_FIXED(4, 4, 4, 0),
.bpp = 16,
},
{
DRM_FORMAT(ARGB4444),
BITS_RGBA_FIXED(4, 4, 4, 4),
.bpp = 16,
.opaque_substitute = DRM_FORMAT_XRGB4444,
},
{
DRM_FORMAT(XBGR4444),
BITS_RGBA_FIXED(4, 4, 4, 0),
.bpp = 16,
},
{
DRM_FORMAT(ABGR4444),
BITS_RGBA_FIXED(4, 4, 4, 4),
.bpp = 16,
.opaque_substitute = DRM_FORMAT_XBGR4444,
},
{
DRM_FORMAT(RGBX4444),
BITS_RGBA_FIXED(4, 4, 4, 0),
.bpp = 16,
# if __BYTE_ORDER == __LITTLE_ENDIAN
GL_FORMAT(GL_RGBA),
GL_TYPE(GL_UNSIGNED_SHORT_4_4_4_4),
......@@ -110,6 +132,7 @@ static const struct pixel_format_info pixel_format_table[] = {
{
DRM_FORMAT(RGBA4444),
BITS_RGBA_FIXED(4, 4, 4, 4),
.bpp = 16,
.opaque_substitute = DRM_FORMAT_RGBX4444,
# if __BYTE_ORDER == __LITTLE_ENDIAN
GL_FORMAT(GL_RGBA),
......@@ -119,35 +142,41 @@ static const struct pixel_format_info pixel_format_table[] = {
{
DRM_FORMAT(BGRX4444),
BITS_RGBA_FIXED(4, 4, 4, 0),
.bpp = 16,
},
{
DRM_FORMAT(BGRA4444),
BITS_RGBA_FIXED(4, 4, 4, 4),
.bpp = 16,
.opaque_substitute = DRM_FORMAT_BGRX4444,
},
{
DRM_FORMAT(XRGB1555),
BITS_RGBA_FIXED(5, 5, 5, 0),
.depth = 15,
.addfb_legacy_depth = 15,
.bpp = 16,
},
{
DRM_FORMAT(ARGB1555),
BITS_RGBA_FIXED(5, 5, 5, 1),
.bpp = 16,
.opaque_substitute = DRM_FORMAT_XRGB1555,
},
{
DRM_FORMAT(XBGR1555),
BITS_RGBA_FIXED(5, 5, 5, 0),
.bpp = 16,
},
{
DRM_FORMAT(ABGR1555),
BITS_RGBA_FIXED(5, 5, 5, 1),
.bpp = 16,
.opaque_substitute = DRM_FORMAT_XBGR1555,
},
{
DRM_FORMAT(RGBX5551),
BITS_RGBA_FIXED(5, 5, 5, 0),
.bpp = 16,
# if __BYTE_ORDER == __LITTLE_ENDIAN
GL_FORMAT(GL_RGBA),
GL_TYPE(GL_UNSIGNED_SHORT_5_5_5_1),
......@@ -156,6 +185,7 @@ static const struct pixel_format_info pixel_format_table[] = {
{
DRM_FORMAT(RGBA5551),
BITS_RGBA_FIXED(5, 5, 5, 1),
.bpp = 16,
.opaque_substitute = DRM_FORMAT_RGBX5551,
# if __BYTE_ORDER == __LITTLE_ENDIAN
GL_FORMAT(GL_RGBA),
......@@ -165,16 +195,18 @@ static const struct pixel_format_info pixel_format_table[] = {
{
DRM_FORMAT(BGRX5551),
BITS_RGBA_FIXED(5, 5, 5, 0),
.bpp = 16,
},
{
DRM_FORMAT(BGRA5551),
BITS_RGBA_FIXED(5, 5, 5, 1),
.bpp = 16,
.opaque_substitute = DRM_FORMAT_BGRX5551,
},
{
DRM_FORMAT(RGB565),
BITS_RGBA_FIXED(5, 6, 5, 0),
.depth = 16,
.addfb_legacy_depth = 16,
.bpp = 16,
# if __BYTE_ORDER == __LITTLE_ENDIAN
GL_FORMAT(GL_RGB),
......@@ -185,21 +217,24 @@ static const struct pixel_format_info pixel_format_table[] = {
{
DRM_FORMAT(BGR565),
BITS_RGBA_FIXED(5, 6, 5, 0),
.bpp = 16,
},
{
DRM_FORMAT(RGB888),
BITS_RGBA_FIXED(8, 8, 8, 0),
.bpp = 24,
},
{
DRM_FORMAT(BGR888),
BITS_RGBA_FIXED(8, 8, 8, 0),
.bpp = 24,
GL_FORMAT(GL_RGB),
GL_TYPE(GL_UNSIGNED_BYTE),
},
{
DRM_FORMAT(XRGB8888),
BITS_RGBA_FIXED(8, 8, 8, 0),
.depth = 24,
.addfb_legacy_depth = 24,
.bpp = 32,
GL_FORMAT(GL_BGRA_EXT),
GL_TYPE(GL_UNSIGNED_BYTE),
......@@ -213,7 +248,7 @@ static const struct pixel_format_info pixel_format_table[] = {
DRM_FORMAT(ARGB8888),
BITS_RGBA_FIXED(8, 8, 8, 8),
.opaque_substitute = DRM_FORMAT_XRGB8888,
.depth = 32,
.addfb_legacy_depth = 32,
.bpp = 32,
GL_FORMAT(GL_BGRA_EXT),
GL_TYPE(GL_UNSIGNED_BYTE),
......@@ -226,6 +261,7 @@ static const struct pixel_format_info pixel_format_table[] = {
{
DRM_FORMAT(XBGR8888),
BITS_RGBA_FIXED(8, 8, 8, 0),
.bpp = 32,
GL_FORMAT(GL_RGBA),
GL_TYPE(GL_UNSIGNED_BYTE),
#if __BYTE_ORDER == __LITTLE_ENDIAN
......@@ -237,6 +273,7 @@ static const struct pixel_format_info pixel_format_table[] = {
{
DRM_FORMAT(ABGR8888),
BITS_RGBA_FIXED(8, 8, 8, 8),
.bpp = 32,
.opaque_substitute = DRM_FORMAT_XBGR8888,
GL_FORMAT(GL_RGBA),
GL_TYPE(GL_UNSIGNED_BYTE),
......@@ -249,6 +286,7 @@ static const struct pixel_format_info pixel_format_table[] = {
{
DRM_FORMAT(RGBX8888),
BITS_RGBA_FIXED(8, 8, 8, 0),
.bpp = 32,
#if __BYTE_ORDER == __LITTLE_ENDIAN
PIXMAN_FMT(r8g8b8x8),
#else
......@@ -258,6 +296,7 @@ static const struct pixel_format_info pixel_format_table[] = {
{
DRM_FORMAT(RGBA8888),
BITS_RGBA_FIXED(8, 8, 8, 8),
.bpp = 32,
.opaque_substitute = DRM_FORMAT_RGBX8888,
#if __BYTE_ORDER == __LITTLE_ENDIAN
PIXMAN_FMT(r8g8b8a8),
......@@ -268,6 +307,7 @@ static const struct pixel_format_info pixel_format_table[] = {
{
DRM_FORMAT(BGRX8888),
BITS_RGBA_FIXED(8, 8, 8, 0),
.bpp = 32,
#if __BYTE_ORDER == __LITTLE_ENDIAN
PIXMAN_FMT(b8g8r8x8),
#else
......@@ -277,6 +317,7 @@ static const struct pixel_format_info pixel_format_table[] = {
{
DRM_FORMAT(BGRA8888),
BITS_RGBA_FIXED(8, 8, 8, 8),
.bpp = 32,
.opaque_substitute = DRM_FORMAT_BGRX8888,
#if __BYTE_ORDER == __LITTLE_ENDIAN
PIXMAN_FMT(b8g8r8a8),
......@@ -287,7 +328,7 @@ static const struct pixel_format_info pixel_format_table[] = {
{
DRM_FORMAT(XRGB2101010),
BITS_RGBA_FIXED(10, 10, 10, 0),
.depth = 30,
.addfb_legacy_depth = 30,
.bpp = 32,
#if __BYTE_ORDER == __LITTLE_ENDIAN
PIXMAN_FMT(x2r10g10b10),
......@@ -296,6 +337,7 @@ static const struct pixel_format_info pixel_format_table[] = {
{
DRM_FORMAT(ARGB2101010),
BITS_RGBA_FIXED(10, 10, 10, 2),
.bpp = 32,
.opaque_substitute = DRM_FORMAT_XRGB2101010,
#if __BYTE_ORDER == __LITTLE_ENDIAN
PIXMAN_FMT(a2r10g10b10),
......@@ -304,6 +346,7 @@ static const struct pixel_format_info pixel_format_table[] = {
{
DRM_FORMAT(XBGR2101010),
BITS_RGBA_FIXED(10, 10, 10, 0),
.bpp = 32,
# if __BYTE_ORDER == __LITTLE_ENDIAN
GL_FORMAT(GL_RGBA),
GL_TYPE(GL_UNSIGNED_INT_2_10_10_10_REV_EXT),
......@@ -313,6 +356,7 @@ static const struct pixel_format_info pixel_format_table[] = {
{
DRM_FORMAT(ABGR2101010),
BITS_RGBA_FIXED(10, 10, 10, 2),
.bpp = 32,
.opaque_substitute = DRM_FORMAT_XBGR2101010,
# if __BYTE_ORDER == __LITTLE_ENDIAN
GL_FORMAT(GL_RGBA),
......@@ -323,46 +367,72 @@ static const struct pixel_format_info pixel_format_table[] = {
{
DRM_FORMAT(RGBX1010102),
BITS_RGBA_FIXED(10, 10, 10, 0),
.bpp = 32,
},
{
DRM_FORMAT(RGBA1010102),
BITS_RGBA_FIXED(10, 10, 10, 2),
.bpp = 32,
.opaque_substitute = DRM_FORMAT_RGBX1010102,
},
{
DRM_FORMAT(BGRX1010102),
BITS_RGBA_FIXED(10, 10, 10, 0),
.bpp = 32,
},
{
DRM_FORMAT(BGRA1010102),
BITS_RGBA_FIXED(10, 10, 10, 2),
.bpp = 32,
.opaque_substitute = DRM_FORMAT_BGRX1010102,
},
{
DRM_FORMAT(XBGR16161616),
BITS_RGBA_FIXED(16, 16, 16, 0),
.bpp = 64,
#if __BYTE_ORDER__ == __LITTLE_ENDIAN
GL_FORMAT(GL_RGBA16_EXT),
GL_TYPE(GL_UNSIGNED_SHORT),
#endif
},
{
DRM_FORMAT(ABGR16161616),
BITS_RGBA_FIXED(16, 16, 16, 16),
.bpp = 64,
.opaque_substitute = DRM_FORMAT_XBGR16161616,
#if __BYTE_ORDER__ == __LITTLE_ENDIAN
GL_FORMAT(GL_RGBA16_EXT),
GL_TYPE(GL_UNSIGNED_SHORT),
#endif
},
{
DRM_FORMAT(XBGR16161616F),
BITS_RGBA_FLOAT(16, 16, 16, 0),
.bpp = 64,
#if __BYTE_ORDER__ == __LITTLE_ENDIAN
GL_FORMAT(GL_RGBA16F),
GL_TYPE(GL_HALF_FLOAT),
#endif
},
{
DRM_FORMAT(ABGR16161616F),
BITS_RGBA_FLOAT(16, 16, 16, 16),
.bpp = 64,
.opaque_substitute = DRM_FORMAT_XBGR16161616F,
#if __BYTE_ORDER__ == __LITTLE_ENDIAN
GL_FORMAT(GL_RGBA16F),
GL_TYPE(GL_HALF_FLOAT),
#endif
},
{
DRM_FORMAT(XRGB16161616F),
BITS_RGBA_FLOAT(16, 16, 16, 0),
.bpp = 64,
},
{
DRM_FORMAT(ARGB16161616F),
BITS_RGBA_FLOAT(16, 16, 16, 16),
.bpp = 64,
.opaque_substitute = DRM_FORMAT_XRGB16161616F,
},
{
......@@ -507,6 +577,7 @@ static const struct pixel_format_info pixel_format_table[] = {
},
{
DRM_FORMAT(XYUV8888),
.bpp = 32,
},
};
......@@ -599,16 +670,34 @@ pixel_format_get_info_by_opaque_substitute(uint32_t format)
return NULL;
}
WL_EXPORT unsigned int
pixel_format_hsub(const struct pixel_format_info *info,
unsigned int plane)
{
/* We don't support any formats where the first plane is subsampled. */
if (plane == 0 || info->hsub == 0)
return 1;
return info->hsub;
}
WL_EXPORT unsigned int
pixel_format_vsub(const struct pixel_format_info *info,
unsigned int plane)
{
/* We don't support any formats where the first plane is subsampled. */
if (plane == 0 || info->vsub == 0)
return 1;
return info->vsub;
}
WL_EXPORT unsigned int
pixel_format_width_for_plane(const struct pixel_format_info *info,
unsigned int plane,
unsigned int width)
{
/* We don't support any formats where the first plane is subsampled. */
if (plane == 0 || !info->hsub)
return width;
return width / info->hsub;
return width / pixel_format_hsub(info, plane);
}
WL_EXPORT unsigned int
......@@ -616,11 +705,7 @@ pixel_format_height_for_plane(const struct pixel_format_info *info,
unsigned int plane,
unsigned int height)
{
/* We don't support any formats where the first plane is subsampled. */
if (plane == 0 || !info->vsub)
return height;
return height / info->vsub;
return height / pixel_format_vsub(info, plane);
}
#ifdef HAVE_HUMAN_FORMAT_MODIFIER
......
......@@ -42,6 +42,10 @@ struct pixel_format_info {
/** The DRM format name without the DRM_FORMAT_ prefix. */
const char *drm_format_name;
/** If true, is only for internal use and should not be advertised to
* clients to allow them to create buffers of this format. */
bool hide_from_clients;
/** If non-zero, number of planes in base (non-modified) format. */
int num_planes;
......@@ -76,9 +80,10 @@ struct pixel_format_info {
/** If set, this format can be used with the legacy drmModeAddFB()
* function (not AddFB2), using this and the bpp member. */
int depth;
int addfb_legacy_depth;
/** See 'depth' member above. */
/** Number of bits required to store a single pixel, for
* single-planar formats. */
int bpp;
/** Horizontal subsampling; if non-zero, divide the width by this
......@@ -247,6 +252,36 @@ pixel_format_get_opaque_substitute(const struct pixel_format_info *format);
const struct pixel_format_info *
pixel_format_get_info_by_opaque_substitute(uint32_t format);
/**
* Return the horizontal subsampling factor for a given plane
*
* When horizontal subsampling is effective, a sampler bound to a secondary
* plane must bind the sampler with a smaller effective width. This function
* returns the subsampling factor to use for the given plane.
*
* @param format Pixel format info structure
* @param plane Zero-indexed plane number
* @returns Horizontal subsampling factor for the given plane
*/
unsigned int
pixel_format_hsub(const struct pixel_format_info *format,
unsigned int plane);
/**
* Return the vertical subsampling factor for a given plane
*
* When vertical subsampling is effective, a sampler bound to a secondary
* plane must bind the sampler with a smaller effective height. This function
* returns the subsampling factor to use for the given plane.
*
* @param format Pixel format info structure
* @param plane Zero-indexed plane number
* @returns Vertical subsampling factor for the given plane
*/
unsigned int
pixel_format_vsub(const struct pixel_format_info *format,
unsigned int plane);
/**
* Return the effective sampling width for a given plane
*
......
This diff is collapsed.
......@@ -150,12 +150,13 @@ x8r8g8b8_to_ycbcr8_bt601(uint32_t xrgb,
* plane 0: Y plane, [7:0] Y
* plane 1: Cb plane, [7:0] Cb
* plane 2: Cr plane, [7:0] Cr
* 2x2 subsampled Cb (1) and Cr (2) planes
* YUV420: 2x2 subsampled Cb (1) and Cr (2) planes
* YUV444: no subsampling
*/
static struct yuv_buffer *
yuv420_create_buffer(struct client *client,
uint32_t drm_format,
pixman_image_t *rgb_image)
y_u_v_create_buffer(struct client *client,
uint32_t drm_format,
pixman_image_t *rgb_image)
{
struct yuv_buffer *buf;
size_t bytes;
......@@ -172,27 +173,29 @@ yuv420_create_buffer(struct client *client,
uint8_t *u_row;
uint8_t *v_row;
uint32_t argb;
int sub = (drm_format == DRM_FORMAT_YUV420) ? 2 : 1;
assert(drm_format == DRM_FORMAT_YUV420);
assert(drm_format == DRM_FORMAT_YUV420 ||
drm_format == DRM_FORMAT_YUV444);
width = pixman_image_get_width(rgb_image);
height = pixman_image_get_height(rgb_image);
rgb_pixels = pixman_image_get_data(rgb_image);
rgb_stride_bytes = pixman_image_get_stride(rgb_image);
/* Full size Y, quarter U and V */
bytes = width * height + (width / 2) * (height / 2) * 2;
/* Full size Y plus quarter U and V */
bytes = width * height + (width / sub) * (height / sub) * 2;
buf = yuv_buffer_create(client, bytes, width, height, width, drm_format);
y_base = buf->data;
u_base = y_base + width * height;
v_base = u_base + (width / 2) * (height / 2);
v_base = u_base + (width / sub) * (height / sub);
for (y = 0; y < height; y++) {
rgb_row = rgb_pixels + (y / 2 * 2) * rgb_stride_bytes;
y_row = y_base + y * width;
u_row = u_base + (y / 2) * (width / 2);
v_row = v_base + (y / 2) * (width / 2);
u_row = u_base + (y / sub) * (width / sub);
v_row = v_base + (y / sub) * (width / sub);
for (x = 0; x < width; x++) {
/*
......@@ -207,10 +210,10 @@ yuv420_create_buffer(struct client *client,
* do the necessary filtering/averaging/siting or
* alternate Cb/Cr rows.
*/
if ((y & 1) == 0 && (x & 1) == 0) {
if ((y & (sub - 1)) == 0 && (x & (sub - 1)) == 0) {
x8r8g8b8_to_ycbcr8_bt601(argb, y_row + x,
u_row + x / 2,
v_row + x / 2);
u_row + x / sub,
v_row + x / sub);
} else {
x8r8g8b8_to_ycbcr8_bt601(argb, y_row + x,
NULL, NULL);
......@@ -435,7 +438,8 @@ show_window_with_yuv(struct client *client, struct yuv_buffer *buf)
static const struct yuv_case yuv_cases[] = {
#define FMT(x) DRM_FORMAT_ ##x, #x
{ FMT(YUV420), yuv420_create_buffer },
{ FMT(YUV420), y_u_v_create_buffer },
{ FMT(YUV444), y_u_v_create_buffer },
{ FMT(NV12), nv12_create_buffer },
{ FMT(YUYV), yuyv_create_buffer },
{ FMT(XYUV8888), xyuv8888_create_buffer },
......