2018-10-03 21:46:18 +00:00
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
// Copyright (c) 2018, Yuxuan Shui <yshuiv7@gmail.com>
|
|
|
|
|
|
|
|
#pragma once
|
2018-12-31 14:27:18 +00:00
|
|
|
|
2019-01-27 19:34:26 +00:00
|
|
|
#include <stdbool.h>
|
|
|
|
|
2019-01-20 16:53:39 +00:00
|
|
|
#include "compiler.h"
|
2019-02-26 23:52:37 +00:00
|
|
|
#include "kernel.h"
|
|
|
|
#include "region.h"
|
|
|
|
#include "x.h"
|
2018-10-03 21:46:18 +00:00
|
|
|
|
2018-12-31 14:27:18 +00:00
|
|
|
typedef struct session session_t;
|
|
|
|
typedef struct win win;
|
2019-02-26 23:52:37 +00:00
|
|
|
|
|
|
|
struct backend_operations;
|
|
|
|
|
|
|
|
typedef struct backend_base {
|
|
|
|
struct backend_operations *ops;
|
|
|
|
xcb_connection_t *c;
|
|
|
|
xcb_window_t root;
|
|
|
|
// ...
|
|
|
|
} backend_t;
|
|
|
|
|
|
|
|
enum image_operations {
|
2019-03-09 13:37:32 +00:00
|
|
|
// Invert the color of the entire image, `reg_op` ignored
|
|
|
|
IMAGE_OP_INVERT_COLOR_ALL,
|
|
|
|
// Dim the entire image, argument is the percentage. `reg_op` ignored
|
|
|
|
IMAGE_OP_DIM_ALL,
|
2019-03-04 21:37:22 +00:00
|
|
|
// Multiply the alpha channel by the argument
|
2019-02-26 23:52:37 +00:00
|
|
|
IMAGE_OP_APPLY_ALPHA,
|
2019-03-04 21:37:22 +00:00
|
|
|
// Same as APPLY_ALPHA, but `reg_op` is ignored and the operation applies to the
|
|
|
|
// full image
|
|
|
|
IMAGE_OP_APPLY_ALPHA_ALL,
|
2019-03-09 18:01:18 +00:00
|
|
|
// Change the effective size of the image, without touching the backing image
|
|
|
|
// itself. When the image is used, the backing image should be tiled to fill its
|
|
|
|
// effective size. `reg_op` and `reg_visibile` is ignored. `arg` is two integers,
|
|
|
|
// width and height, in that order.
|
|
|
|
IMAGE_OP_RESIZE_TILE,
|
2019-02-26 23:52:37 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct backend_operations {
|
2018-10-03 21:46:18 +00:00
|
|
|
|
|
|
|
// =========== Initialization ===========
|
|
|
|
|
|
|
|
/// Initialize the backend, prepare for rendering to the target window.
|
|
|
|
/// Here is how you should choose target window:
|
|
|
|
/// 1) if ps->overlay is not XCB_NONE, use that
|
|
|
|
/// 2) use ps->root otherwise
|
|
|
|
/// XXX make the target window a parameter
|
2019-03-07 21:08:37 +00:00
|
|
|
backend_t *(*init)(session_t *) attr_nonnull(1);
|
2019-02-26 23:52:37 +00:00
|
|
|
void (*deinit)(backend_t *backend_data) __attribute__((nonnull(1)));
|
2018-10-03 21:46:18 +00:00
|
|
|
|
|
|
|
/// Called when rendering will be stopped for an unknown amount of
|
|
|
|
/// time (e.g. screen is unredirected). Free some resources.
|
2019-02-26 23:52:37 +00:00
|
|
|
void (*pause)(backend_t *backend_data, session_t *ps);
|
2018-10-03 21:46:18 +00:00
|
|
|
|
|
|
|
/// Called before rendering is resumed
|
2019-02-26 23:52:37 +00:00
|
|
|
void (*resume)(backend_t *backend_data, session_t *ps);
|
2018-10-03 21:46:18 +00:00
|
|
|
|
|
|
|
/// Called when root property changed, returns the new
|
|
|
|
/// backend_data. Even if the backend_data changed, all
|
|
|
|
/// the existing win_data returned by prepare_win should
|
|
|
|
/// remain valid.
|
|
|
|
///
|
|
|
|
/// Optional
|
2019-02-26 23:52:37 +00:00
|
|
|
void *(*root_change)(backend_t *backend_data, session_t *ps);
|
2019-01-01 14:23:51 +00:00
|
|
|
|
2018-10-03 21:46:18 +00:00
|
|
|
// =========== Rendering ============
|
|
|
|
|
|
|
|
/// Called before any compose() calls.
|
|
|
|
///
|
|
|
|
/// Usually the backend should clear the buffer, or paint a background
|
|
|
|
/// on the buffer (usually the wallpaper).
|
|
|
|
///
|
2019-03-05 20:27:03 +00:00
|
|
|
/// Optional
|
|
|
|
void (*prepare)(backend_t *backend_data, const region_t *reg_damage);
|
2018-10-03 21:46:18 +00:00
|
|
|
|
2019-03-04 21:37:22 +00:00
|
|
|
/**
|
|
|
|
* Paint the content of an image onto the (possibly buffered)
|
|
|
|
* target picture.
|
|
|
|
*
|
|
|
|
* @param backend_data the backend data
|
|
|
|
* @param image_data the image to paint
|
|
|
|
* @param dst_x, dst_y the top left corner of the image in the target
|
|
|
|
* @param reg_paint the clip region, in target coordinates
|
|
|
|
* @param reg_visibile the visible region, in target coordinates
|
|
|
|
*/
|
2019-02-26 23:52:37 +00:00
|
|
|
void (*compose)(backend_t *backend_data, void *image_data, int dst_x, int dst_y,
|
2019-03-04 21:37:22 +00:00
|
|
|
const region_t *reg_paint, const region_t *reg_visible);
|
2018-10-03 21:46:18 +00:00
|
|
|
|
2019-03-05 20:27:04 +00:00
|
|
|
/// Fill rectangle of target, mostly for debug purposes, optional.
|
|
|
|
void (*fill_rectangle)(backend_t *backend_data, double r, double g, double b, double a,
|
|
|
|
int x, int y, int width, int height, const region_t *clip);
|
|
|
|
|
2018-10-03 21:46:18 +00:00
|
|
|
/// Blur a given region on of the target.
|
2019-03-04 21:37:22 +00:00
|
|
|
bool (*blur)(backend_t *backend_data, double opacity, const region_t *reg_blur,
|
|
|
|
const region_t *reg_visible) attr_nonnull(1, 3, 4);
|
2018-10-03 21:46:18 +00:00
|
|
|
|
|
|
|
/// Present the buffered target picture onto the screen. If target
|
2018-12-31 23:08:45 +00:00
|
|
|
/// is not buffered, this should be NULL. Otherwise, it should always
|
|
|
|
/// be non-NULL.
|
2018-10-03 21:46:18 +00:00
|
|
|
///
|
|
|
|
/// Optional
|
2019-03-04 21:37:22 +00:00
|
|
|
void (*present)(backend_t *backend_data) attr_nonnull(1);
|
2018-10-03 21:46:18 +00:00
|
|
|
|
|
|
|
/**
|
2019-02-26 23:52:37 +00:00
|
|
|
* Bind a X pixmap to the backend's internal image data structure.
|
2018-10-03 21:46:18 +00:00
|
|
|
*
|
2019-02-26 23:52:37 +00:00
|
|
|
* @param backend_data backend data
|
|
|
|
* @param pixmap X pixmap to bind
|
|
|
|
* @param fmt information of the pixmap's visual
|
|
|
|
* @param owned whether the ownership of the pixmap is transfered to the backend
|
|
|
|
* @return backend internal data structure bound with this pixmap
|
2018-10-03 21:46:18 +00:00
|
|
|
*/
|
2019-02-26 23:52:37 +00:00
|
|
|
void *(*bind_pixmap)(backend_t *backend_data, xcb_pixmap_t pixmap,
|
|
|
|
struct xvisual_info fmt, bool owned);
|
2018-10-03 21:46:18 +00:00
|
|
|
|
2019-02-26 23:52:37 +00:00
|
|
|
/// Create a shadow image based on the parameters
|
|
|
|
void *(*render_shadow)(backend_t *backend_data, int width, int height,
|
2019-03-04 22:58:11 +00:00
|
|
|
const conv *kernel, double r, double g, double b, double a);
|
2018-10-03 21:46:18 +00:00
|
|
|
|
|
|
|
// ============ Resource management ===========
|
|
|
|
|
2019-02-26 23:52:37 +00:00
|
|
|
// XXX Thoughts: calling release_image and render_* for every config notify
|
2018-10-03 21:46:18 +00:00
|
|
|
// is wasteful, since there can be multiple such notifies per drawing.
|
|
|
|
// But if we don't, it can mean there will be a state where is window is
|
|
|
|
// mapped and visible, but there is no win_data attached to it. We don't
|
2018-12-31 23:08:45 +00:00
|
|
|
// want to break that assumption as for now. We need to reconsider this.
|
2018-10-03 21:46:18 +00:00
|
|
|
|
2019-02-26 23:52:37 +00:00
|
|
|
/// Free resources associated with an image data structure
|
|
|
|
void (*release_image)(backend_t *backend_data, void *img_data)
|
2019-03-09 01:39:18 +00:00
|
|
|
attr_nonnull(1, 2);
|
2018-10-03 21:46:18 +00:00
|
|
|
|
|
|
|
// =========== Query ===========
|
|
|
|
|
|
|
|
/// Return if a window has transparent content. Guaranteed to only
|
|
|
|
/// be called after render_win is called.
|
2018-12-31 23:08:45 +00:00
|
|
|
///
|
|
|
|
/// This function is needed because some backend might change the content of the
|
|
|
|
/// window (e.g. when using a custom shader with the glx backend), so we only now
|
|
|
|
/// the transparency after the window is rendered
|
2019-02-26 23:52:37 +00:00
|
|
|
bool (*is_image_transparent)(backend_t *backend_data, void *image_data)
|
2019-03-09 01:39:18 +00:00
|
|
|
attr_nonnull(1, 2);
|
2019-01-01 14:23:51 +00:00
|
|
|
|
2019-01-08 21:31:52 +00:00
|
|
|
/// Get the age of the buffer content we are currently rendering ontop
|
|
|
|
/// of. The buffer that has just been `present`ed has a buffer age of 1.
|
|
|
|
/// Everytime `present` is called, buffers get older. Return -1 if the
|
|
|
|
/// buffer is empty.
|
2019-02-26 23:52:37 +00:00
|
|
|
int (*buffer_age)(backend_t *backend_data);
|
2019-01-08 21:31:52 +00:00
|
|
|
|
2019-01-27 19:45:40 +00:00
|
|
|
/// The maximum number buffer_age might return.
|
|
|
|
int max_buffer_age;
|
|
|
|
|
2019-02-26 23:52:37 +00:00
|
|
|
// =========== Post-processing ============
|
|
|
|
/**
|
|
|
|
* Manipulate an image
|
|
|
|
*
|
|
|
|
* @param backend_data backend data
|
2019-03-04 21:37:22 +00:00
|
|
|
* @param op the operation to perform
|
|
|
|
* @param image_data an image data structure returned by the backend
|
|
|
|
* @param reg_op the clip region, define the part of the image to be
|
|
|
|
* operated on.
|
|
|
|
* @param reg_visible define the part of the image that will eventually
|
|
|
|
* be visible on screen. this is a hint to the backend
|
|
|
|
* for optimization purposes.
|
|
|
|
* @param args extra arguments, operation specific
|
|
|
|
* @return a new image data structure containing the result
|
2019-02-26 23:52:37 +00:00
|
|
|
*/
|
2019-03-04 21:37:22 +00:00
|
|
|
bool (*image_op)(backend_t *backend_data, enum image_operations op, void *image_data,
|
|
|
|
const region_t *reg_op, const region_t *reg_visible, void *args);
|
2019-02-26 23:52:37 +00:00
|
|
|
|
2019-03-04 21:37:22 +00:00
|
|
|
/// Create another instance of the `image_data`. All `image_op` calls on the
|
|
|
|
/// returned image should not affect the original image
|
|
|
|
void *(*copy)(backend_t *base, const void *image_data, const region_t *reg_visible);
|
2019-02-26 23:52:37 +00:00
|
|
|
|
2019-01-01 14:23:51 +00:00
|
|
|
// =========== Hooks ============
|
|
|
|
/// Let the backend hook into the event handling queue
|
2019-02-26 23:52:37 +00:00
|
|
|
};
|
|
|
|
|
2019-03-07 21:08:37 +00:00
|
|
|
typedef backend_t *(*backend_init_fn)(session_t *ps) attr_nonnull(1);
|
2018-10-03 21:46:18 +00:00
|
|
|
|
2019-03-07 21:08:37 +00:00
|
|
|
extern struct backend_operations *backend_list[];
|
2018-10-03 21:46:18 +00:00
|
|
|
|
|
|
|
bool default_is_win_transparent(void *, win *, void *);
|
|
|
|
bool default_is_frame_transparent(void *, win *, void *);
|
2019-01-27 19:29:02 +00:00
|
|
|
void paint_all_new(session_t *ps, win *const t, bool ignore_damage) attr_nonnull(1);
|
2019-01-08 21:31:52 +00:00
|
|
|
|
|
|
|
// vim: set noet sw=8 ts=8 :
|