From d0e1bc77408c618e13134aa95424baa82c0febd4 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Tue, 2 Apr 2024 02:45:00 +0100 Subject: [PATCH] backend: add new backend interface according to #1191 Signed-off-by: Yuxuan Shui --- src/backend/backend.h | 234 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) diff --git a/src/backend/backend.h b/src/backend/backend.h index 0a90a91f26..764e3e04e1 100644 --- a/src/backend/backend.h +++ b/src/backend/backend.h @@ -119,7 +119,241 @@ typedef struct { // Intentionally left blank } *image_handle; +/// A mask for various backend operations. +/// +/// The mask is composed of both a mask region and a mask image. The resulting mask +/// is the intersection of the two. The mask image can be modified by the `corner_radius` +/// and `inverted` properties. Note these properties have no effect on the mask region. +struct backend_mask { + /// Mask image, can be NULL. + /// + /// Mask image must be an image that was created with the + /// `BACKEND_IMAGE_FORMAT_MASK` format. Using an image with a wrong format as mask + /// is undefined behavior. + image_handle image; + /// Clip region, in source image's coordinate. + region_t region; + /// Corner radius of the mask image, the corners of the mask image will be + /// rounded. + double corner_radius; + /// Origin of the mask image, in the source image's coordinate. + struct coord origin; + /// Whether the mask image should be inverted. + bool inverted; +}; + +struct backend_blur_args { + /// The blur context + void *blur_context; + /// The mask for the blur operation, cannot be NULL. + struct backend_mask *mask; + /// Source image + image_handle source_image; + /// Opacity of the blurred image + double opacity; +}; + +struct backend_blit_args { + /// Source image, can be NULL. + image_handle source_image; + /// Mask for the source image. Cannot be NULL. + struct backend_mask *mask; + /// Custom shader for this blit operation. + void *shader; + /// Opacity of the source image. + double opacity; + /// Dim level of the source image. + double dim; + /// Brightness limit of the source image. Source image + /// will be normalized so that the maximum brightness is + /// this value. + double max_brightness; + /// Corner radius of the source image. The corners of + /// the source image will be rounded. + double corner_radius; + /// Effective size of the source image, set where the corners + /// of the image are. + int ewidth, eheight; + /// Border width of the source image. This is used with + /// `corner_radius` to create a border for the rounded corners. + int border_width; + /// Whether the source image should be inverted. + bool color_inverted; +}; + +enum backend_image_format { + /// A format that can be used for normal rendering, and binding + /// X pixmaps. + /// Images created with `bind_pixmap` have this format automatically. + BACKEND_IMAGE_FORMAT_PIXMAP, + /// Like `BACKEND_IMAGE_FORMAT_PIXMAP`, but the image has a higher + /// precision. Support is optional. + BACKEND_IMAGE_FORMAT_PIXMAP_HIGH, + /// A format that can be used for masks. + BACKEND_IMAGE_FORMAT_MASK, +}; + +enum backend_image_capability { + /// Image can be sampled from. This is required for `blit` and `blur` source + /// images. All images except the back buffer should have this capability. + /// Note that `copy_area` should work without this capability, this is so that + /// blurring the back buffer could be done. + BACKEND_IMAGE_CAP_SRC = 1 << 0, + /// Image can be rendered to. This is required for target images of any operation. + /// All images except bound X pixmaps should have this capability. + BACKEND_IMAGE_CAP_DST = 1 << 1, +}; + +struct backend_ops_v2 { + /// Check if an optional image format is supported by the backend. + bool (*is_format_supported)(struct backend_base *backend_data, + enum backend_image_format format) attr_nonnull(1); + + /// Return the capabilities of an image. + uint32_t (*image_capabilities)(struct backend_base *backend_data, image_handle image) + attr_nonnull(1, 2); + + /// Multiply the alpha channel of the target image by a given value. + /// + /// @param backend_data backend data + /// @param target an image handle, cannot be NULL. + /// @param alpha the alpha value to multiply + /// @param region the region to apply the alpha, in the target image's + /// coordinate. + bool (*apply_alpha)(struct backend_base *backend_data, image_handle target, + double alpha, const region_t *region) attr_nonnull(1, 2, 4); + + /// Copy pixels from a source image on to the target image. + /// + /// Some effects may be applied. If the region specified by the mask + /// contains parts that are outside the source image, the source image + /// will be repeated to fit. + /// + /// Source and target MUST NOT be the same image. + /// + /// @param backend_data backend data + /// @param origin the origin of the operation, in the target image's + /// coordinate. + /// @param target an image handle, cannot be NULL. + /// @param args arguments for blit + /// @return whether the operation is successful + bool (*blit)(struct backend_base *backend_data, struct coord origin, + image_handle target, struct backend_blit_args *args) + attr_nonnull(1, 3, 4); + + /// Blur a given region of a source image and store the result in the + /// target image. + /// + /// The blur operation might access pixels outside the mask region, the + /// amount of pixels accessed can be queried with `get_blur_size`. If + /// pixels outside the source image are accessed, the result will be + /// clamped to the edge of the source image. + /// + /// Source and target may be the same image. + /// + /// @param backend_data backend data + /// @param origin the origin of the operation, in the target image's + /// coordinate. + /// @param target an image handle, cannot be NULL. + /// @param args argument for blur + /// @return whether the operation is successful + bool (*blur)(struct backend_base *backend_data, struct coord origin, + image_handle target, struct backend_blur_args *args) + attr_nonnull(1, 3, 4); + + /// Direct copy of pixels from a source image on to the target image. + /// This is a simpler version of `blit`, without any effects. Note unlike `blit`, + /// if `region` tries to sample from outside the source image, instead of + /// repeating, the result will be clamped to the edge of the source image. + /// + /// Source and target MUST NOT be the same image. + /// + /// @param backend_data backend data + /// @param origin the origin of the operation, in the target image's + /// coordinate. + /// @param target an image handle, cannot be NULL. + /// @param source an image handle, cannot be NULL. + /// @param region the region to copy, in the source image's coordinate. + /// @return whether the operation is successful + bool (*copy_area)(struct backend_base *backend_data, struct coord origin, + image_handle target, image_handle source, const region_t *region) + attr_nonnull(1, 3, 4, 5); + + /// Similar to `copy_area`, but is specialized for copying from a higher + /// precision format to a lower precision format. It has 2 major differences from + /// `copy_area`: + /// + /// 1. This function _may_ use dithering when copying from a higher precision + /// format to a lower precision format. But this is not required. + /// 2. This function only needs to support copying from an image with the SRC + /// capability. Unlike `copy_area`, which supports copying from any image. + /// + /// It's perfectly legal to have this pointing to the same function as + /// `copy_area`, if the backend doesn't support dithering. + /// + /// @param backend_data backend data + /// @param origin the origin of the operation, in the target image's + /// coordinate. + /// @param target an image handle, cannot be NULL. + /// @param source an image handle, cannot be NULL. + /// @param region the region to copy, in the source image's coordinate. + /// @return whether the operation is successful + bool (*copy_area_quantize)(struct backend_base *backend_data, struct coord origin, + image_handle target, image_handle source, + const region_t *region) attr_nonnull(1, 3, 4, 5); + + /// Initialize an image with a given color value. If the image has a mask format, + /// only the alpha channel of the color is used. + /// + /// @param backend_data backend data + /// @param target an image handle, cannot be NULL. + /// @param color the color to fill the image with + /// @return whether the operation is successful + bool (*clear)(struct backend_base *backend_data, image_handle target, + struct color color) attr_nonnull(1, 2); + + /// Create a new, uninitialized image with the given format and size. + /// + /// @param backend_data backend data + /// @param format the format of the image + /// @param size the size of the image + image_handle (*new_image)(struct backend_base *backend_data, + enum backend_image_format format, geometry_t size) + attr_nonnull(1); + + /// Acquire the image handle of the back buffer. + /// + /// @param backend_data backend data + image_handle (*back_buffer)(struct backend_base *backend_data); + + /// Bind a X pixmap to the backend's internal image data structure. + /// + /// @param backend_data backend data + /// @param pixmap X pixmap to bind + /// @param fmt information of the pixmap's visual + /// @return backend specific image handle for the pixmap. May be + /// NULL. + image_handle (*bind_pixmap)(struct backend_base *backend_data, xcb_pixmap_t pixmap, + struct xvisual_info fmt) attr_nonnull(1); + + /// Free resources associated with an image data structure. Releasing the image + /// returned by `back_buffer` should be a no-op. + /// + /// @param image the image to be released, cannot be NULL. + /// @return if this image is created by `bind_pixmap`, the X pixmap; 0 + /// otherwise. + xcb_pixmap_t (*release_image)(struct backend_base *backend_data, image_handle image) + attr_nonnull(1, 2); + + /// Present the back buffer to the target window. Ideally the backend should keep + /// track of the region of the back buffer that has been updated, and use relevant + /// mechanism (when possible) to present only the updated region. + bool (*present)(struct backend_base *backend_data) attr_nonnull(1); +}; + struct backend_operations { + // =========== V2 =========== + struct backend_ops_v2 v2; // =========== Initialization =========== /// Initialize the backend, prepare for rendering to the target window.