summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stone <daniels@collabora.com>2017-04-04 17:54:20 +0100
committerPekka Paalanen <pekka.paalanen@collabora.co.uk>2017-04-07 12:28:36 +0300
commit903721a6215f474787b5daf02761fbcb1d3a0bb5 (patch)
tree4ca9885cbcf650dc1bec914ed4b76c8cc8b51041
parentb030897b380be4ac8089deecc3db6967dfe7923e (diff)
libweston: Add pixel-format helpers
Rather than duplicating knowledge of pixel formats across several components, create a custom central repository. Signed-off-by: Daniel Stone <daniels@collabora.com> [Pekka: fix include paths and two copy-pastas] Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
-rw-r--r--Makefile.am5
-rw-r--r--libweston/pixel-formats.c430
-rw-r--r--libweston/pixel-formats.h194
3 files changed, 628 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index 8ecc90cd..94b1c143 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -71,7 +71,8 @@ install-libweston_moduleLTLIBRARIES install-moduleLTLIBRARIES: install-libLTLIBR
lib_LTLIBRARIES = libweston-@LIBWESTON_MAJOR@.la
libweston_@LIBWESTON_MAJOR@_la_CPPFLAGS = $(AM_CPPFLAGS) -DIN_WESTON
-libweston_@LIBWESTON_MAJOR@_la_CFLAGS = $(AM_CFLAGS) $(COMPOSITOR_CFLAGS) $(LIBUNWIND_CFLAGS)
+libweston_@LIBWESTON_MAJOR@_la_CFLAGS = $(AM_CFLAGS) \
+ $(COMPOSITOR_CFLAGS) $(LIBUNWIND_CFLAGS) $(LIBDRM_CFLAGS)
libweston_@LIBWESTON_MAJOR@_la_LIBADD = $(COMPOSITOR_LIBS) $(LIBUNWIND_LIBS) \
$(DLOPEN_LIBS) -lm $(CLOCK_GETTIME_LIBS) \
$(LIBINPUT_BACKEND_LIBS) libshared.la
@@ -105,6 +106,8 @@ libweston_@LIBWESTON_MAJOR@_la_SOURCES = \
libweston/timeline-object.h \
libweston/linux-dmabuf.c \
libweston/linux-dmabuf.h \
+ libweston/pixel-formats.c \
+ libweston/pixel-formats.h \
shared/helpers.h \
shared/matrix.c \
shared/matrix.h \
diff --git a/libweston/pixel-formats.c b/libweston/pixel-formats.c
new file mode 100644
index 00000000..df84a9f3
--- /dev/null
+++ b/libweston/pixel-formats.c
@@ -0,0 +1,430 @@
+/*
+ * Copyright © 2016 Collabora, Ltd.
+ *
+ * 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.
+ *
+ * Author: Daniel Stone <daniels@collabora.com>
+ */
+
+#include "config.h"
+
+#include <endian.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <drm_fourcc.h>
+
+#include "helpers.h"
+#include "wayland-util.h"
+#include "pixel-formats.h"
+
+#if ENABLE_EGL
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#define GL_FORMAT(fmt) .gl_format = (fmt)
+#define GL_TYPE(type) .gl_type = (type)
+#define SAMPLER_TYPE(type) .sampler_type = (type)
+#else
+#define GL_FORMAT(fmt) .gl_format = 0
+#define GL_TYPE(type) .gl_type = 0
+#define SAMPLER_TYPE(type) .sampler_type = 0
+#endif
+
+#include "weston-egl-ext.h"
+
+/**
+ * Table of DRM formats supported by Weston; RGB, ARGB and YUV formats are
+ * supported. Indexed/greyscale formats, and formats not containing complete
+ * colour channels, are not supported.
+ */
+static const struct pixel_format_info pixel_format_table[] = {
+ {
+ .format = DRM_FORMAT_XRGB4444,
+ },
+ {
+ .format = DRM_FORMAT_ARGB4444,
+ .opaque_substitute = DRM_FORMAT_XRGB4444,
+ },
+ {
+ .format = DRM_FORMAT_XBGR4444,
+ },
+ {
+ .format = DRM_FORMAT_ABGR4444,
+ .opaque_substitute = DRM_FORMAT_XBGR4444,
+ },
+ {
+ .format = DRM_FORMAT_RGBX4444,
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+ GL_FORMAT(GL_RGBA),
+ GL_TYPE(GL_UNSIGNED_SHORT_4_4_4_4),
+#endif
+ },
+ {
+ .format = DRM_FORMAT_RGBA4444,
+ .opaque_substitute = DRM_FORMAT_RGBX4444,
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+ GL_FORMAT(GL_RGBA),
+ GL_TYPE(GL_UNSIGNED_SHORT_4_4_4_4),
+#endif
+ },
+ {
+ .format = DRM_FORMAT_BGRX4444,
+ },
+ {
+ .format = DRM_FORMAT_BGRA4444,
+ .opaque_substitute = DRM_FORMAT_BGRX4444,
+ },
+ {
+ .format = DRM_FORMAT_XRGB1555,
+ .depth = 15,
+ .bpp = 16,
+ },
+ {
+ .format = DRM_FORMAT_ARGB1555,
+ .opaque_substitute = DRM_FORMAT_XRGB1555,
+ },
+ {
+ .format = DRM_FORMAT_XBGR1555,
+ },
+ {
+ .format = DRM_FORMAT_ABGR1555,
+ .opaque_substitute = DRM_FORMAT_XBGR1555,
+ },
+ {
+ .format = DRM_FORMAT_RGBX5551,
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+ GL_FORMAT(GL_RGBA),
+ GL_TYPE(GL_UNSIGNED_SHORT_5_5_5_1),
+#endif
+ },
+ {
+ .format = DRM_FORMAT_RGBA5551,
+ .opaque_substitute = DRM_FORMAT_RGBX5551,
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+ GL_FORMAT(GL_RGBA),
+ GL_TYPE(GL_UNSIGNED_SHORT_5_5_5_1),
+#endif
+ },
+ {
+ .format = DRM_FORMAT_BGRX5551,
+ },
+ {
+ .format = DRM_FORMAT_BGRA5551,
+ .opaque_substitute = DRM_FORMAT_BGRX5551,
+ },
+ {
+ .format = DRM_FORMAT_RGB565,
+ .depth = 16,
+ .bpp = 16,
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+ GL_FORMAT(GL_RGB),
+ GL_TYPE(GL_UNSIGNED_SHORT_5_6_5),
+#endif
+ },
+ {
+ .format = DRM_FORMAT_BGR565,
+ },
+ {
+ .format = DRM_FORMAT_RGB888,
+ },
+ {
+ .format = DRM_FORMAT_BGR888,
+ GL_FORMAT(GL_RGB),
+ GL_TYPE(GL_UNSIGNED_BYTE),
+ },
+ {
+ .format = DRM_FORMAT_XRGB8888,
+ .depth = 24,
+ .bpp = 32,
+ GL_FORMAT(GL_BGRA_EXT),
+ GL_TYPE(GL_UNSIGNED_BYTE),
+ },
+ {
+ .format = DRM_FORMAT_ARGB8888,
+ .opaque_substitute = DRM_FORMAT_XRGB8888,
+ .depth = 32,
+ .bpp = 32,
+ GL_FORMAT(GL_BGRA_EXT),
+ GL_TYPE(GL_UNSIGNED_BYTE),
+ },
+ {
+ .format = DRM_FORMAT_XBGR8888,
+ GL_FORMAT(GL_RGBA),
+ GL_TYPE(GL_UNSIGNED_BYTE),
+ },
+ {
+ .format = DRM_FORMAT_ABGR8888,
+ .opaque_substitute = DRM_FORMAT_XBGR8888,
+ GL_FORMAT(GL_RGBA),
+ GL_TYPE(GL_UNSIGNED_BYTE),
+ },
+ {
+ .format = DRM_FORMAT_RGBX8888,
+ },
+ {
+ .format = DRM_FORMAT_RGBA8888,
+ .opaque_substitute = DRM_FORMAT_RGBX8888,
+ },
+ {
+ .format = DRM_FORMAT_BGRX8888,
+ },
+ {
+ .format = DRM_FORMAT_BGRA8888,
+ .opaque_substitute = DRM_FORMAT_BGRX8888,
+ },
+ {
+ .format = DRM_FORMAT_XRGB2101010,
+ .depth = 30,
+ .bpp = 32,
+ },
+ {
+ .format = DRM_FORMAT_ARGB2101010,
+ .opaque_substitute = DRM_FORMAT_XRGB2101010,
+ },
+ {
+ .format = DRM_FORMAT_XBGR2101010,
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+ GL_FORMAT(GL_RGBA),
+ GL_TYPE(GL_UNSIGNED_INT_2_10_10_10_REV_EXT),
+#endif
+ },
+ {
+ .format = DRM_FORMAT_ABGR2101010,
+ .opaque_substitute = DRM_FORMAT_XBGR2101010,
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+ GL_FORMAT(GL_RGBA),
+ GL_TYPE(GL_UNSIGNED_INT_2_10_10_10_REV_EXT),
+#endif
+ },
+ {
+ .format = DRM_FORMAT_RGBX1010102,
+ },
+ {
+ .format = DRM_FORMAT_RGBA1010102,
+ .opaque_substitute = DRM_FORMAT_RGBX1010102,
+ },
+ {
+ .format = DRM_FORMAT_BGRX1010102,
+ },
+ {
+ .format = DRM_FORMAT_BGRA1010102,
+ .opaque_substitute = DRM_FORMAT_BGRX1010102,
+ },
+ {
+ .format = DRM_FORMAT_YUYV,
+ SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
+ .num_planes = 1,
+ .hsub = 2,
+ },
+ {
+ .format = DRM_FORMAT_YVYU,
+ SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
+ .num_planes = 1,
+ .chroma_order = ORDER_VU,
+ .hsub = 2,
+ },
+ {
+ .format = DRM_FORMAT_UYVY,
+ SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
+ .num_planes = 1,
+ .luma_chroma_order = ORDER_CHROMA_LUMA,
+ .hsub = 2,
+ },
+ {
+ .format = DRM_FORMAT_VYUY,
+ SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
+ .num_planes = 1,
+ .luma_chroma_order = ORDER_CHROMA_LUMA,
+ .chroma_order = ORDER_VU,
+ .hsub = 2,
+ },
+ {
+ .format = DRM_FORMAT_NV12,
+ SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
+ .num_planes = 2,
+ .hsub = 2,
+ .vsub = 2,
+ },
+ {
+ .format = DRM_FORMAT_NV21,
+ SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
+ .num_planes = 2,
+ .chroma_order = ORDER_VU,
+ .hsub = 2,
+ .vsub = 2,
+ },
+ {
+ .format = DRM_FORMAT_NV16,
+ SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
+ .num_planes = 2,
+ .hsub = 2,
+ .vsub = 1,
+ },
+ {
+ .format = DRM_FORMAT_NV61,
+ SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
+ .num_planes = 2,
+ .chroma_order = ORDER_VU,
+ .hsub = 2,
+ .vsub = 1,
+ },
+ {
+ .format = DRM_FORMAT_NV24,
+ SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
+ .num_planes = 2,
+ },
+ {
+ .format = DRM_FORMAT_NV42,
+ SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
+ .num_planes = 2,
+ .chroma_order = ORDER_VU,
+ },
+ {
+ .format = DRM_FORMAT_YUV410,
+ SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
+ .num_planes = 3,
+ .hsub = 4,
+ .vsub = 4,
+ },
+ {
+ .format = DRM_FORMAT_YVU410,
+ SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
+ .num_planes = 3,
+ .chroma_order = ORDER_VU,
+ .hsub = 4,
+ .vsub = 4,
+ },
+ {
+ .format = DRM_FORMAT_YUV411,
+ SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
+ .num_planes = 3,
+ .hsub = 4,
+ .vsub = 1,
+ },
+ {
+ .format = DRM_FORMAT_YVU411,
+ SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
+ .num_planes = 3,
+ .chroma_order = ORDER_VU,
+ .hsub = 4,
+ .vsub = 1,
+ },
+ {
+ .format = DRM_FORMAT_YUV420,
+ SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
+ .num_planes = 3,
+ .hsub = 2,
+ .vsub = 2,
+ },
+ {
+ .format = DRM_FORMAT_YVU420,
+ SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
+ .num_planes = 3,
+ .chroma_order = ORDER_VU,
+ .hsub = 2,
+ .vsub = 2,
+ },
+ {
+ .format = DRM_FORMAT_YUV422,
+ SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
+ .num_planes = 3,
+ .hsub = 2,
+ .vsub = 1,
+ },
+ {
+ .format = DRM_FORMAT_YVU422,
+ SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
+ .num_planes = 3,
+ .chroma_order = ORDER_VU,
+ .hsub = 2,
+ .vsub = 1,
+ },
+ {
+ .format = DRM_FORMAT_YUV444,
+ SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
+ .num_planes = 3,
+ },
+ {
+ .format = DRM_FORMAT_YVU444,
+ SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
+ .num_planes = 3,
+ .chroma_order = ORDER_VU,
+ },
+};
+
+WL_EXPORT const struct pixel_format_info *
+pixel_format_get_info(uint32_t format)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_LENGTH(pixel_format_table); i++) {
+ if (pixel_format_table[i].format == format)
+ return &pixel_format_table[i];
+ }
+
+ return NULL;
+}
+
+WL_EXPORT unsigned int
+pixel_format_get_plane_count(const struct pixel_format_info *info)
+{
+ return info->num_planes ? info->num_planes : 1;
+}
+
+WL_EXPORT bool
+pixel_format_is_opaque(const struct pixel_format_info *info)
+{
+ return !info->opaque_substitute;
+}
+
+WL_EXPORT const struct pixel_format_info *
+pixel_format_get_opaque_substitute(const struct pixel_format_info *info)
+{
+ if (!info->opaque_substitute)
+ return info;
+ else
+ return pixel_format_get_info(info->opaque_substitute);
+}
+
+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;
+}
+
+WL_EXPORT unsigned int
+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;
+}
diff --git a/libweston/pixel-formats.h b/libweston/pixel-formats.h
new file mode 100644
index 00000000..b16aae32
--- /dev/null
+++ b/libweston/pixel-formats.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright © 2016 Collabora, Ltd.
+ *
+ * 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.
+ *
+ * Author: Daniel Stone <daniels@collabora.com>
+ */
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+/**
+ * Contains information about pixel formats, mapping format codes from
+ * wl_shm and drm_fourcc.h (which are deliberately identical, but for the
+ * special cases of WL_SHM_ARGB8888 and WL_SHM_XRGB8888) into various
+ * sets of information. Helper functions are provided for dealing with these
+ * raw structures.
+ */
+struct pixel_format_info {
+ /** DRM/wl_shm format code */
+ uint32_t format;
+
+ /** If non-zero, number of planes in base (non-modified) format. */
+ int num_planes;
+
+ /** If format contains alpha channel, opaque equivalent of format,
+ * i.e. alpha channel replaced with X. */
+ uint32_t opaque_substitute;
+
+ /** How the format should be sampled, expressed in terms of tokens
+ * from the EGL_WL_bind_wayland_display extension. If not set,
+ * assumed to be either RGB or RGBA, depending on whether or not
+ * the format contains an alpha channel. The samplers may still
+ * return alpha even for opaque formats; users must manually set
+ * the alpha channel to 1.0 (or ignore it) if the format is
+ * opaque. */
+ uint32_t sampler_type;
+
+ /** GL format, if data can be natively/directly uploaded. Note that
+ * whilst DRM formats are little-endian unless explicitly specified,
+ * (i.e. DRM_FORMAT_ARGB8888 is stored BGRA as sequential bytes in
+ * memory), GL uses the sequential byte order, so that format maps to
+ * GL_BGRA_EXT plus GL_UNSIGNED_BYTE. To add to the confusion, the
+ * explicitly-sized types (e.g. GL_UNSIGNED_SHORT_5_5_5_1) read in
+ * machine-endian order, so for these types, the correspondence
+ * depends on endianness. */
+ int gl_format;
+
+ /** GL data type, if data can be natively/directly uploaded. */
+ int gl_type;
+
+ /** If set, this format can be used with the legacy drmModeAddFB()
+ * function (not AddFB2), using this and the bpp member. */
+ int depth;
+
+ /** See 'depth' member above. */
+ int bpp;
+
+ /** Horizontal subsampling; if non-zero, divide the width by this
+ * member to obtain the number of columns in the source buffer for
+ * secondary planes only. Stride is not affected by horizontal
+ * subsampling. */
+ int hsub;
+
+ /** Vertical subsampling; if non-zero, divide the height by this
+ * member to obtain the number of rows in the source buffer for
+ * secondary planes only. */
+ int vsub;
+
+ /* Ordering of chroma components. */
+ enum {
+ ORDER_UV = 0,
+ ORDER_VU,
+ } chroma_order;
+
+ /* If packed YUV (num_planes == 1), ordering of luma/chroma
+ * components. */
+ enum {
+ ORDER_LUMA_CHROMA = 0,
+ ORDER_CHROMA_LUMA,
+ } luma_chroma_order;
+};
+
+/**
+ * Get pixel format information for a DRM format code
+ *
+ * Given a DRM format code, return a pixel format info structure describing
+ * the properties of that format.
+ *
+ * @param format DRM format code to get info for
+ * @returns A pixel format structure (must not be freed), or NULL if the
+ * format could not be found
+ */
+const struct pixel_format_info *pixel_format_get_info(uint32_t format);
+
+/**
+ * Get number of planes used by a pixel format
+ *
+ * Given a pixel format info structure, return the number of planes
+ * required for a buffer. Note that this is not necessarily identical to
+ * the number of samplers required to be bound, as two views into a single
+ * plane are sometimes required.
+ *
+ * @param format Pixel format info structure
+ * @returns Number of planes required for the format
+ */
+unsigned int
+pixel_format_get_plane_count(const struct pixel_format_info *format);
+
+/**
+ * Determine if a pixel format is opaque or contains alpha
+ *
+ * Returns whether or not the pixel format is opaque, or contains a
+ * significant alpha channel. Note that the suggested EGL sampler type may
+ * still sample undefined data into the alpha channel; users must consider
+ * alpha as 1.0 if the format is opaque, and not rely on the sampler to
+ * return this when sampling from the alpha channel.
+ *
+ * @param format Pixel format info structure
+ * @returns True if the format is opaque, or false if it has significant alpha
+ */
+bool pixel_format_is_opaque(const struct pixel_format_info *format);
+
+/**
+ * Get compatible opaque equivalent for a format
+ *
+ * Given a pixel format info structure, return a format which is wholly
+ * compatible with the input format, but opaque, ignoring the alpha channel.
+ * If an alpha format is provided, but the content is known to all be opaque,
+ * then this can be used as a substitute to avoid blending.
+ *
+ * If the input format is opaque, this function will return the input format.
+ *
+ * @param format Pixel format info structure
+ * @returns A pixel format info structure for the compatible opaque substitute
+ */
+const struct pixel_format_info *
+pixel_format_get_opaque_substitute(const struct pixel_format_info *format);
+
+/**
+ * Return the effective sampling width 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 effective width to use for the sampler, i.e. dividing by hsub.
+ *
+ * If horizontal subsampling is not in effect, this will be equal to the
+ * width.
+ *
+ * @param format Pixel format info structure
+ * @param plane Zero-indexed plane number
+ * @param width Width of the buffer
+ * @returns Effective width for sampling
+ */
+unsigned int
+pixel_format_width_for_plane(const struct pixel_format_info *format,
+ unsigned int plane,
+ unsigned int width);
+
+/**
+ * Return the effective sampling height for a given plane
+ *
+ * When vertical subsampling is in effect, a sampler bound to a secondary
+ * plane must bind the sampler with a smaller effective height. This function
+ * returns the effective height to use for the sampler, i.e. dividing by vsub.
+ *
+ * If vertical subsampling is not in effect, this will be equal to the height.
+ *
+ * @param format Pixel format info structure
+ * @param plane Zero-indexed plane number
+ * @param height Height of the buffer
+ * @returns Effective width for sampling
+ */
+unsigned int
+pixel_format_height_for_plane(const struct pixel_format_info *format,
+ unsigned int plane,
+ unsigned int height);