Skip to content

Commit

Permalink
backend: add new backend interface according to #1191
Browse files Browse the repository at this point in the history
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
  • Loading branch information
yshui committed Apr 10, 2024
1 parent 1d94af4 commit f382405
Showing 1 changed file with 227 additions and 0 deletions.
227 changes: 227 additions & 0 deletions src/backend/backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,234 @@ 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.
///
/// @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.
///
/// @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.
///
/// @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
///
/// @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.
Expand Down

0 comments on commit f382405

Please sign in to comment.