Compare commits

...

7 Commits

Author SHA1 Message Date
Maxim Solovyov fa42eac7a5
common: remove OPENGL_MAX_DEPTH and it's uses
scientists haven't proven the existence of depths greater than 32 yet.
2024-04-29 17:17:59 +03:00
Yuxuan Shui d6e3335cfd
string_utils: strtod_simple should not succeed if no number is parsed
So things like "+.", ".", "+", etc. will no longer parse successfully.

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
2024-04-28 18:24:07 +01:00
Yuxuan Shui c5e58da1ba
unittest: use test.h setup hook to setup logging
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
2024-04-28 18:23:41 +01:00
Yuxuan Shui e5e618fb50
renderer: fix handling of root pixmap changes
I thought to myself, "I will add this later", then proceeded to forget
about this...

The `root_damaged` flag in `struct session` I added in anticipation for
this is actually not enough. Imagine this:

frame 0 -> frame 1 -> frame 2 (root changed) -> frame 3

frame 2 will be rendered with the `root_damaged` flag set, all good.
But `frame 3` wouldn't, and if it has buffer age 2, i.e. it's rendered
on top of the base of `frame 1`, then the result will be wrong because
frame 1 and 3 has different root background. So instead I added a
`root_image_generation` that is incremented every time the root image
changes.

Fixes #1247

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
2024-04-28 13:17:12 +01:00
Yuxuan Shui 09b58035f4
renderer/layout: remove unused code
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
2024-04-28 13:02:15 +01:00
Yuxuan Shui 4aa283df98
renderer: move monitor repaint init to its own function
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
2024-04-28 12:48:26 +01:00
Yuxuan Shui cf08a3b7a5
build: make libconfig mandatory
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
2024-04-20 16:25:08 +01:00
19 changed files with 68 additions and 101 deletions

View File

@ -72,7 +72,7 @@ jobs:
executor: e
steps:
- build:
build-config: -Dopengl=false -Ddbus=false -Dregex=false -Dconfig_file=false
build-config: -Dopengl=false -Ddbus=false -Dregex=false
release:
executor: e
steps:
@ -104,7 +104,7 @@ jobs:
steps:
- build:
cc: clang
build-config: -Dopengl=false -Ddbus=false -Dregex=false -Dconfig_file=false
build-config: -Dopengl=false -Ddbus=false -Dregex=false
clang_nogl:
executor: e
steps:

View File

@ -40,6 +40,7 @@
* picom now uses some OpenGL 4.3 features.
* picom now optionally depends on `rtkit` at runtime to give itself realtime scheduling priority.
* `libconfig` is now a mandatory dependency.
# v11.2 (2024-Feb-13)

View File

@ -39,8 +39,8 @@ Assuming you already have all the usual building tools installed (e.g. gcc, pyth
* xcb-present
* xcb-glx
* pixman
* libconfig
* libdbus (optional, disable with the `-Ddbus=false` meson configure flag)
* libconfig (optional, disable with the `-Dconfig_file=false` meson configure flag)
* libGL, libEGL, libepoxy (optional, disable with the `-Dopengl=false` meson configure flag)
* libpcre2 (optional, disable with the `-Dregex=false` meson configure flag)
* libev

View File

@ -1,5 +1,4 @@
option('sanitize', type: 'boolean', value: false, description: 'Build with sanitizers enabled (deprecated)')
option('config_file', type: 'boolean', value: true, description: 'Enable config file support')
option('regex', type: 'boolean', value: true, description: 'Enable regex support in window conditions')
option('vsync_drm', type: 'boolean', value: false, description: 'Enable support for using drm for vsync')

View File

@ -371,12 +371,6 @@ static image_handle
glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt) {
GLXPixmap *glxpixmap = NULL;
auto gd = (struct _glx_data *)base;
// Retrieve pixmap parameters, if they aren't provided
if (fmt.visual_depth > OPENGL_MAX_DEPTH) {
log_error("Requested depth %d higher than max possible depth %d.",
fmt.visual_depth, OPENGL_MAX_DEPTH);
return NULL;
}
if (fmt.visual_depth < 0) {
log_error("Pixmap %#010x with invalid depth %d", pixmap, fmt.visual_depth);

View File

@ -416,9 +416,6 @@ c2_lptr_t *c2_parse(c2_lptr_t **pcondlst, const char *pattern, void *data) {
}
TEST_CASE(c2_parse) {
log_init_tls();
// log_add_target_tls(stderr_logger_new());
char str[1024];
c2_lptr_t *cond = c2_parse(NULL, "name = \"xterm\"", NULL);
struct atom *atoms = init_mock_atoms();

View File

@ -70,9 +70,6 @@
#define US_PER_SEC 1000000L
#define MS_PER_SEC 1000
/// @brief Maximum OpenGL FBConfig depth.
#define OPENGL_MAX_DEPTH 32
/// @brief Maximum OpenGL buffer age.
#define CGLX_MAX_BUFFER_AGE 5
@ -199,6 +196,9 @@ typedef struct session {
paint_t root_tile_paint;
/// The backend data the root pixmap bound to
image_handle root_image;
/// The root pixmap generation, incremented everytime
/// the root pixmap changes
uint64_t root_image_generation;
/// A region of the size of the screen.
region_t screen_reg;
/// Picture of root window. Destination of painting in no-DBE painting
@ -271,8 +271,6 @@ typedef struct session {
/// Render command builder
struct command_builder *command_builder;
struct renderer *renderer;
/// Whether the root image has been changed since last render
bool root_damaged;
/// Whether all windows are currently redirected.
bool redirected;
/// Pre-generated alpha pictures.

View File

@ -887,15 +887,7 @@ char *parse_config(options_t *opt, const char *config_file, bool *shadow_enable,
// clang-format on
char *ret = NULL;
#ifdef CONFIG_LIBCONFIG
ret = parse_config_libconfig(opt, config_file, shadow_enable, fading_enable,
hasneg, winopt_mask);
#else
(void)config_file;
(void)shadow_enable;
(void)fading_enable;
(void)hasneg;
(void)winopt_mask;
#endif
return ret;
}

View File

@ -17,9 +17,7 @@
#include "uthash_extra.h"
#ifdef CONFIG_LIBCONFIG
#include <libconfig.h>
#endif
#include "compiler.h"
#include "kernel.h"
@ -311,7 +309,6 @@ void parse_debug_options(struct debug_options *);
*/
bool condlst_add(c2_lptr_t **, const char *);
#ifdef CONFIG_LIBCONFIG
const char *xdg_config_home(void);
char **xdg_config_dirs(void);
@ -326,7 +323,6 @@ char **xdg_config_dirs(void);
char *
parse_config_libconfig(options_t *, const char *config_file, bool *shadow_enable,
bool *fading_enable, bool *hasneg, win_option_mask_t *winopt_mask);
#endif
void set_default_winopts(options_t *, win_option_mask_t *, bool shadow_enable,
bool fading_enable, bool blur_enable);

View File

@ -3,13 +3,5 @@
#pragma once
#include <xcb/xcb.h>
#include "compiler.h"
#ifdef CONFIG_LIBCONFIG
int inspect_main(int argc, char **argv, const char *config_file);
#else
static inline int inspect_main(int argc attr_unused, char **argv attr_unused,
const char *config_file attr_unused) {
return 0;
}
#endif

View File

@ -11,7 +11,7 @@ srcs = [ files('picom.c', 'win.c', 'c2.c', 'x.c', 'config.c', 'vsync.c', 'utils.
'diagnostic.c', 'string_utils.c', 'render.c', 'kernel.c', 'log.c',
'options.c', 'event.c', 'cache.c', 'atom.c', 'file_watch.c', 'statistics.c',
'vblank.c', 'transition.c', 'wm.c', 'renderer/layout.c', 'renderer/command_builder.c',
'renderer/renderer.c', 'renderer/damage.c') ]
'renderer/renderer.c', 'renderer/damage.c', 'config_libconfig.c', 'inspect.c') ]
picom_inc = include_directories('.')
cflags = []
@ -34,6 +34,7 @@ endforeach
foreach i : required_xcb_packages
base_deps += [dependency(i, version: '>=1.12.0', required: true)]
endforeach
base_deps += [dependency('libconfig', version: '>=1.4', required: true)]
if not cc.has_header('uthash.h')
error('Dependency uthash not found')
@ -41,12 +42,6 @@ endif
deps = []
if get_option('config_file')
deps += [dependency('libconfig', version: '>=1.4', required: true)]
cflags += ['-DCONFIG_LIBCONFIG']
srcs += [ 'config_libconfig.c', 'inspect.c' ]
endif
if get_option('regex')
pcre = dependency('libpcre2-8', required: true)
cflags += ['-DCONFIG_REGEX_PCRE']
@ -97,9 +92,7 @@ if get_option('unittest')
test('picom unittest', picom, args: [ '--unittest' ])
endif
if get_option('config_file')
install_symlink('picom-inspect', install_dir: 'bin', pointing_to: 'picom')
endif
install_symlink('picom-inspect', install_dir: 'bin', pointing_to: 'picom')
if cc.has_argument('-fsanitize=fuzzer')
c2_fuzz = executable('c2_fuzz', srcs + ['fuzzer/c2.c'],

View File

@ -746,11 +746,6 @@ bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
log_error("Failed to query info of pixmap %#010x.", pixmap);
return false;
}
if (r->depth > OPENGL_MAX_DEPTH) {
log_error("Requested depth %d higher than %d.", depth,
OPENGL_MAX_DEPTH);
return false;
}
depth = r->depth;
width = r->width;
height = r->height;

View File

@ -34,9 +34,7 @@ struct picom_option {
// clang-format off
static const struct option *longopts = NULL;
static const struct picom_option picom_options[] = {
#ifdef CONFIG_LIBCONFIG
{"config" , required_argument, 256, NULL , "Path to the configuration file."},
#endif
{"help" , no_argument , 'h', NULL , "Print this help message and exit."},
{"shadow-radius" , required_argument, 'r', NULL , "The blur radius for shadows. (default 12)"},
{"shadow-opacity" , required_argument, 'o', NULL , "The translucency for shadows. (default .75)"},

View File

@ -1189,12 +1189,12 @@ void root_damaged(session_t *ps) {
ps->root_image = ps->backend_data->ops->v2.bind_pixmap(
ps->backend_data, pixmap, x_get_visual_info(&ps->c, visual));
ps->root_image_generation += 1;
if (!ps->root_image) {
err:
log_error("Failed to bind root back pixmap");
}
}
ps->root_damaged = true;
}
// Mark screen damaged
@ -1846,7 +1846,7 @@ static void draw_callback_impl(EV_P_ session_t *ps, int revents attr_unused) {
auto render_start_us =
(uint64_t)now.tv_sec * 1000000UL + (uint64_t)now.tv_nsec / 1000;
layout_manager_append_layout(
ps->layout_manager, ps->wm,
ps->layout_manager, ps->wm, ps->root_image_generation,
(struct geometry){.width = ps->root_width,
.height = ps->root_height});
bool succeeded = renderer_render(
@ -2888,3 +2888,11 @@ int PICOM_MAIN(int argc, char **argv) {
return ret_code;
}
#ifdef UNIT_TEST
static void unittest_setup(void) {
log_init_tls();
// log_add_target_tls(stderr_logger_new());
}
void (*test_h_unittest_setup)(void) = unittest_setup;
#endif

View File

@ -147,9 +147,8 @@ void layout_manager_damage(struct layout_manager *lm, unsigned buffer_age,
pixman_region32_init(&scratch_region);
pixman_region32_clear(damage);
if (past_layout->size.width != curr_layout->size.width ||
past_layout->size.height != curr_layout->size.height) {
// We might be able to do better for blur size change, but currently we
// don't even support changing that.
past_layout->size.height != curr_layout->size.height ||
past_layout->root_image_generation != curr_layout->root_image_generation) {
pixman_region32_union_rect(damage, damage, 0, 0,
(unsigned)curr_layout->size.width,
(unsigned)curr_layout->size.height);

View File

@ -26,9 +26,6 @@ struct layout_manager {
unsigned current;
/// Mapping from window to its index in the current layout.
struct layer_index *layer_indices;
/// Output render plan.
struct render_plan *plan;
unsigned plan_capacity;
struct list_node free_indices;
// internal
@ -110,8 +107,6 @@ struct layout_manager *layout_manager_new(unsigned max_buffer_age) {
planner->max_buffer_age = max_buffer_age + 1;
planner->current = 0;
planner->layer_indices = NULL;
planner->plan_capacity = 0;
planner->plan = NULL;
list_init_head(&planner->free_indices);
pixman_region32_init(&planner->scratch_region);
for (unsigned i = 0; i <= max_buffer_age; i++) {
@ -133,11 +128,7 @@ void layout_manager_free(struct layout_manager *lm) {
list_remove(&i->free_list);
free(i);
}
for (unsigned i = 0; i < lm->plan_capacity; i++) {
pixman_region32_fini(&lm->plan[i].render);
}
pixman_region32_fini(&lm->scratch_region);
free(lm->plan);
free(lm);
}
@ -152,11 +143,13 @@ void layout_manager_free(struct layout_manager *lm) {
// above.
void layout_manager_append_layout(struct layout_manager *lm, struct wm *wm,
struct geometry size) {
uint64_t root_pixmap_generation, struct geometry size) {
auto prev_layout = &lm->layouts[lm->current];
lm->current = (lm->current + 1) % lm->max_buffer_age;
auto layout = &lm->layouts[lm->current];
command_builder_command_list_free(layout->commands);
layout->root_image_generation = root_pixmap_generation;
unsigned nlayers = wm_stack_num_managed_windows(wm);
if (nlayers > layout->capacity) {
struct layer *new_layers =

View File

@ -71,6 +71,8 @@ struct layer {
/// Layout of windows at a specific frame
struct layout {
struct geometry size;
/// The root image generation, see `struct session::root_image_generation`
uint64_t root_image_generation;
/// Number of layers in `layers`
unsigned len;
/// Capacity of `layers`
@ -88,11 +90,6 @@ struct layout {
struct backend_command *commands;
};
struct render_plan {
region_t render;
const struct layer *layer;
};
struct wm;
struct layout_manager;
@ -101,7 +98,7 @@ struct layout_manager;
/// layouts, with its size chosen at creation time. Calling this will push at new layout
/// at the end of the ring buffer, and remove the oldest layout if the buffer is full.
void layout_manager_append_layout(struct layout_manager *lm, struct wm *wm,
struct geometry size);
uint64_t root_image_generation, struct geometry size);
/// Get the layout `age` frames into the past. Age `0` is the most recently appended
/// layout.
struct layout *layout_manager_layout(struct layout_manager *lm, unsigned age);

View File

@ -421,6 +421,32 @@ static bool renderer_prepare_commands(struct renderer *r, struct backend_base *b
return true;
}
void renderer_ensure_monitor_repaint_ready(struct renderer *r, struct backend_base *backend) {
if (!r->monitor_repaint_pixel) {
r->monitor_repaint_pixel = backend->ops->v2.new_image(
backend, BACKEND_IMAGE_FORMAT_PIXMAP, (struct geometry){1, 1});
BUG_ON(!r->monitor_repaint_pixel);
backend->ops->v2.clear(backend, r->monitor_repaint_pixel,
(struct color){.alpha = 0.5, .red = 0.5});
}
if (!r->monitor_repaint_copy) {
r->monitor_repaint_copy = ccalloc(r->max_buffer_age, image_handle);
for (int i = 0; i < r->max_buffer_age; i++) {
r->monitor_repaint_copy[i] = backend->ops->v2.new_image(
backend, BACKEND_IMAGE_FORMAT_PIXMAP,
(struct geometry){.width = r->canvas_size.width,
.height = r->canvas_size.height});
BUG_ON(!r->monitor_repaint_copy[i]);
}
}
if (!r->monitor_repaint_region) {
r->monitor_repaint_region = ccalloc(r->max_buffer_age, region_t);
for (int i = 0; i < r->max_buffer_age; i++) {
pixman_region32_init(&r->monitor_repaint_region[i]);
}
}
}
/// @return true if a frame is rendered, false if this frame is skipped.
bool renderer_render(struct renderer *r, struct backend_base *backend,
image_handle root_image, struct layout_manager *lm,
@ -448,29 +474,7 @@ bool renderer_render(struct renderer *r, struct backend_base *backend,
}
if (monitor_repaint) {
if (!r->monitor_repaint_pixel) {
r->monitor_repaint_pixel = backend->ops->v2.new_image(
backend, BACKEND_IMAGE_FORMAT_PIXMAP, (struct geometry){1, 1});
BUG_ON(!r->monitor_repaint_pixel);
backend->ops->v2.clear(backend, r->monitor_repaint_pixel,
(struct color){.alpha = 0.5, .red = 0.5});
}
if (!r->monitor_repaint_copy) {
r->monitor_repaint_copy = ccalloc(r->max_buffer_age, image_handle);
for (int i = 0; i < r->max_buffer_age; i++) {
r->monitor_repaint_copy[i] = backend->ops->v2.new_image(
backend, BACKEND_IMAGE_FORMAT_PIXMAP,
(struct geometry){.width = r->canvas_size.width,
.height = r->canvas_size.height});
BUG_ON(!r->monitor_repaint_copy[i]);
}
}
if (!r->monitor_repaint_region) {
r->monitor_repaint_region = ccalloc(r->max_buffer_age, region_t);
for (int i = 0; i < r->max_buffer_age; i++) {
pixman_region32_init(&r->monitor_repaint_region[i]);
}
}
renderer_ensure_monitor_repaint_ready(r, backend);
}
command_builder_build(cb, layout, force_blend, blur_frame, inactive_dim_fixed,

View File

@ -85,6 +85,8 @@ TEST_CASE(mstrextend) {
/// Parse a floating point number of form (+|-)?[0-9]*(\.[0-9]*)
double strtod_simple(const char *src, const char **end) {
double neg = 1;
bool succeeded = false;
*end = src;
if (*src == '-') {
neg = -1;
src++;
@ -95,6 +97,7 @@ double strtod_simple(const char *src, const char **end) {
double ret = 0;
while (*src >= '0' && *src <= '9') {
ret = ret * 10 + (*src - '0');
succeeded = true;
src++;
}
@ -104,13 +107,17 @@ double strtod_simple(const char *src, const char **end) {
while (*src >= '0' && *src <= '9') {
frac += mult * (*src - '0');
mult *= 0.1;
succeeded = true;
src++;
}
ret += frac;
}
*end = src;
return ret * neg;
if (succeeded) {
*end = src;
return ret * neg;
}
return NAN;
}
TEST_CASE(strtod_simple) {
@ -126,6 +133,10 @@ TEST_CASE(strtod_simple) {
result = strtod_simple("+.5", &end);
TEST_EQUAL(result, 0.5);
TEST_EQUAL(*end, '\0');
result = strtod_simple("+.", &end);
TEST_TRUE(safe_isnan(result));
TEST_EQUAL(*end, '+');
}
const char *trim_both(const char *src, size_t *length) {