Skip to content

Commit 51b2135

Browse files
committed
Merge branch 'next' into implement-window-animations
2 parents bb398ab + cd50596 commit 51b2135

14 files changed

+526
-79
lines changed

.github/workflows/codeql-analysis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
languages: ${{ matrix.language }}
3737

3838
# Install dependencies
39-
- run: sudo apt install libxext-dev libxcb1-dev libxcb-damage0-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-render-util0-dev libxcb-render0-dev libxcb-randr0-dev libxcb-composite0-dev libxcb-image0-dev libxcb-present-dev libxcb-xinerama0-dev libxcb-glx0-dev libpixman-1-dev libdbus-1-dev libconfig-dev libgl1-mesa-dev libpcre2-dev libevdev-dev uthash-dev libev-dev libx11-xcb-dev meson ninja-build
39+
- run: sudo apt update && sudo apt install libxext-dev libxcb1-dev libxcb-damage0-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-render-util0-dev libxcb-render0-dev libxcb-randr0-dev libxcb-composite0-dev libxcb-image0-dev libxcb-present-dev libxcb-xinerama0-dev libxcb-glx0-dev libpixman-1-dev libdbus-1-dev libconfig-dev libgl1-mesa-dev libpcre2-dev libevdev-dev uthash-dev libev-dev libx11-xcb-dev meson ninja-build
4040
if: ${{ matrix.language == 'cpp' }}
4141

4242
# Autobuild

README_orig.md History.md

+33
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,38 @@
1+
# Picom History
2+
3+
Picom was forked in 2016 from the original Compton because it seemed to have become unmaintained.
4+
5+
The battle plan of the fork was to refactor it to make the code _possible_ to maintain, so potential contributors won't be scared away when they take a look at the code.
6+
7+
And also to try to fix bugs.
8+
9+
## Rename
10+
11+
In 2019 the project name was changed from Compton to picom (git revision 8ddbeb and following).
12+
13+
### Rationale
14+
15+
Since the inception of this fork, the existence of two compton repositories has caused some number of confusions. Mainly, people will report issues of this fork to the original compton, or report issues of the original compton here. Later, when distros started packaging this fork of compton, some wanted to differentiate the newer compton from the older version. They found themselves having no choice but to invent a name for this fork. This is less than ideal since this has the potential to cause more confusions among users.
16+
17+
Therefore, we decided to move this fork to a new name. Personally, I consider this more than justified since this version of compton has gone through significant changes since it was forked.
18+
19+
### The name
20+
21+
The criteria for a good name were
22+
23+
0. Being short, so it's easy to remember.
24+
1. Pronounceability, again, helps memorability
25+
2. Searchability, so when people search the name, it's easy for them to find this repository.
26+
27+
Of course, choosing a name is never easy, and there is no apparent way to objectively evaluate the names. Yet, we have to solve the aforementioned problems as soon as possible.
28+
29+
In the end, we picked `picom` (a portmanteau of `pico` and `composite`) as our new name. This name might not be perfect, but is what we will move forward with unless there's a compelling reason not to.
30+
31+
132
# Compton
233

34+
This is a copy of the README of the [original Compton project](https://github.com/chjj/compton/).
35+
336
[![Join the chat at https://gitter.im/chjj/compton](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/chjj/compton?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
437

538
__Compton__ is a compositor for X, and a fork of __xcompmgr-dana__.

README.md

+11-40
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,11 @@
11
picom
2-
=======
2+
=====
33

4-
**This is a development branch, bugs to be expected**
5-
6-
This is forked from the original Compton because it seems to have become unmaintained.
7-
8-
The current battle plan of this fork is to refactor it to make the code _possible_ to maintain, so potential contributors won't be scared away when they take a look at the code.
4+
__picom__ is a compositor for X, and a [fork of Compton](History.md).
95

10-
We also try to fix bugs.
11-
12-
You can leave your feedbacks or thoughts in the [discussion tab](https://github.com/yshui/picom/discussions).
6+
**This is a development branch, bugs to be expected**
137

14-
The original README can be found [here](README_orig.md)
8+
You can leave your feedback or thoughts in the [discussion tab](https://github.com/yshui/picom/discussions).
159

1610
## Call for testers
1711

@@ -27,36 +21,6 @@ To test the new backends, add the `--experimental-backends` flag to the command
2721

2822
To report issues with the new backends, please state explicitly you are using the new backends in your report.
2923

30-
## Rename
31-
32-
### Rationale
33-
34-
Since the inception of this fork, the existence of two compton repositories has caused some number of confusions. Mainly, people will report issues of this fork to the original compton, or report issues of the original compton here. Later, when distros started packaging this fork of compton, some wanted to differentiate the newer compton from the older version. They found themselves having no choice but to invent a name for this fork. This is less than ideal since this has the potential to cause more confusions among users.
35-
36-
Therefore, we decided to move this fork to a new name. Personally, I consider this more than justified since this version of compton has gone through significant changes since it was forked.
37-
38-
### The name
39-
40-
The criteria for a good name were
41-
42-
0. Being short, so it's easy to remember.
43-
1. Pronounceability, again, helps memorability
44-
2. Searchability, so when people search the name, it's easy for them to find this repository.
45-
46-
Of course, choosing a name is never easy, and there is no apparent way to objectively evaluate the names. Yet, we have to solve the aforementioned problems as soon as possible.
47-
48-
In the end, we picked `picom` (a portmanteau of `pico` and `composite`) as our new name. This name might not be perfect, but is what we will move forward with unless there's a compelling reason not to.
49-
50-
### Migration
51-
52-
Following the [deprecation process](https://github.com/yshui/picom/issues/114), migration to the new name will be broken into 3 steps:
53-
54-
1. All mentions of `compton` will be updated to `picom` in the code base. `compton` will still be installed, but only as a symlink to `picom`. When `picom` is launched via the symlink, a warning message is printed, alerting the user to migrate. Similarly, the old configuration file names and dbus interface names will still be accepted but warned.
55-
2. 3 major releases after step 1, the warning messages will be prompted to error messages and `picom` will not start when launched via the symlink.
56-
3. 3 major releases after step 2, the symlink will be removed.
57-
58-
The dbus interface and service names are unchanged, so no migration needed for that.
59-
6024
## Change Log
6125

6226
See [Releases](https://github.com/yshui/picom/releases)
@@ -153,3 +117,10 @@ Contributions to the documents and wiki will also be appreciated.
153117
## Contributors
154118

155119
See [CONTRIBUTORS](CONTRIBUTORS)
120+
121+
The README for the [original Compton project](https://github.com/chjj/compton/) can be found [here](History.md#Compton).
122+
123+
## Licensing
124+
125+
picom is free software, made available under the [MIT](LICENSES/MIT) and [MPL-2.0](LICENSES/MPL-2.0) software
126+
licenses. See the individual source files for details.

meson.build

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
project('picom', 'c', version: '8',
1+
project('picom', 'c', version: '9',
22
default_options: ['c_std=c11'])
33

44
cc = meson.get_compiler('c')

meson/install.sh

100644100755
File mode changed.

picom.sample.conf

+3
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,9 @@ blur-background-exclude = [
203203
# General Settings #
204204
#################################
205205

206+
# Enable remote control via D-Bus. See the man page for more details.
207+
# dbus = true
208+
206209
# Daemonize process. Fork to background after initialization. Causes issues with certain (badly-written) drivers.
207210
# daemon = false
208211

src/backend/backend.c

+29
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,37 @@ static void process_window_for_painting(session_t *ps, struct managed_win *w,
102102
pixman_region32_fini(&reg_visible_local);
103103
}
104104

105+
void handle_device_reset(session_t *ps) {
106+
log_error("Device reset detected");
107+
// Wait for reset to complete
108+
// Although ideally the backend should return DEVICE_STATUS_NORMAL after a reset
109+
// is completed, it's not always possible.
110+
//
111+
// According to ARB_robustness (emphasis mine):
112+
//
113+
// "If a reset status other than NO_ERROR is returned and subsequent
114+
// calls return NO_ERROR, the context reset was encountered and
115+
// completed. If a reset status is repeatedly returned, the context **may**
116+
// be in the process of resetting."
117+
//
118+
// Which means it may also not be in the process of resetting. For example on
119+
// AMDGPU devices, Mesa OpenGL always return CONTEXT_RESET after a reset has
120+
// started, completed or not.
121+
//
122+
// So here we blindly wait 5 seconds and hope ourselves best of the luck.
123+
sleep(5);
124+
125+
// Reset picom
126+
log_info("Resetting picom after device reset");
127+
ev_break(ps->loop, EVBREAK_ALL);
128+
}
129+
105130
/// paint all windows
106131
void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
132+
if (ps->backend_data->ops->device_status &&
133+
ps->backend_data->ops->device_status(ps->backend_data) != DEVICE_STATUS_NORMAL) {
134+
return handle_device_reset(ps);
135+
}
107136
if (ps->o.xrender_sync_fence) {
108137
if (ps->xsync_exists && !x_fence_sync(ps->c, ps->sync_fence)) {
109138
log_error("x_fence_sync failed, xrender-sync-fence will be "

src/backend/backend.h

+11
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ typedef struct backend_base {
3232

3333
typedef void (*backend_ready_callback_t)(void *);
3434

35+
// This mimics OpenGL's ARB_robustness extension, which enables detection of GPU context
36+
// resets.
37+
// See: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_robustness.txt, section
38+
// 2.6 "Graphics Reset Recovery".
39+
enum device_status {
40+
DEVICE_STATUS_NORMAL,
41+
DEVICE_STATUS_RESETTING,
42+
};
43+
3544
// When image properties are actually applied to the image, they are applied in a
3645
// particular order:
3746
//
@@ -275,6 +284,8 @@ struct backend_operations {
275284
enum driver (*detect_driver)(backend_t *backend_data);
276285

277286
void (*diagnostics)(backend_t *backend_data);
287+
288+
enum device_status (*device_status)(backend_t *backend_data);
278289
};
279290

280291
extern struct backend_operations *backend_list[];

src/backend/gl/gl_common.c

+29-3
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,11 @@ static void _gl_compose(backend_t *base, struct backend_image *img, GLuint targe
395395
glUniform1f(gd->win_shader.uniform_corner_radius, (float)img->corner_radius);
396396
}
397397
if (gd->win_shader.uniform_border_width >= 0) {
398-
glUniform1f(gd->win_shader.uniform_border_width, (float)img->border_width);
398+
auto border_width = img->border_width;
399+
if (border_width > img->corner_radius) {
400+
border_width = 0;
401+
}
402+
glUniform1f(gd->win_shader.uniform_border_width, (float)border_width);
399403
}
400404

401405
// log_trace("Draw: %d, %d, %d, %d -> %d, %d (%d, %d) z %d\n",
@@ -1554,23 +1558,32 @@ const char *win_shader_glsl = GLSL(330,
15541558
vec4 border_color = texture(tex, vec2(0.0, 0.5));
15551559
if (invert_color) {
15561560
c = vec4(c.aaa - c.rgb, c.a);
1561+
border_color = vec4(border_color.aaa - border_color.rgb, border_color.a);
15571562
}
15581563
c = vec4(c.rgb * (1.0 - dim), c.a) * opacity;
1564+
border_color = vec4(border_color.rgb * (1.0 - dim), border_color.a) * opacity;
15591565

15601566
vec3 rgb_brightness = texelFetch(brightness, ivec2(0, 0), 0).rgb;
15611567
// Ref: https://en.wikipedia.org/wiki/Relative_luminance
15621568
float brightness = rgb_brightness.r * 0.21 +
15631569
rgb_brightness.g * 0.72 +
15641570
rgb_brightness.b * 0.07;
1565-
if (brightness > max_brightness)
1571+
if (brightness > max_brightness) {
15661572
c.rgb = c.rgb * (max_brightness / brightness);
1573+
border_color.rgb = border_color.rgb * (max_brightness / brightness);
1574+
}
1575+
1576+
// Rim color is the color of the outer rim of the window, if there is no
1577+
// border, it's the color of the window itself, otherwise it's the border.
1578+
// Using mix() to avoid a branch here.
1579+
vec4 rim_color = mix(c, border_color, clamp(border_width, 0.0f, 1.0f));
15671580

15681581
vec2 outer_size = vec2(textureSize(tex, 0));
15691582
vec2 inner_size = outer_size - vec2(corner_radius) * 2.0f;
15701583
float rect_distance = rectangle_sdf(texcoord - outer_size / 2.0f,
15711584
inner_size / 2.0f) - corner_radius;
15721585
if (rect_distance > 0.0f) {
1573-
c = (1.0f - clamp(rect_distance, 0.0f, 1.0f)) * border_color;
1586+
c = (1.0f - clamp(rect_distance, 0.0f, 1.0f)) * rim_color;
15741587
} else {
15751588
float factor = clamp(rect_distance + border_width, 0.0f, 1.0f);
15761589
c = (1.0f - factor) * c + factor * border_color;
@@ -1702,6 +1715,7 @@ bool gl_init(struct gl_data *gd, session_t *ps) {
17021715
} else {
17031716
gd->is_nvidia = false;
17041717
}
1718+
gd->has_robustness = gl_has_extension("GL_ARB_robustness");
17051719

17061720
return true;
17071721
}
@@ -1916,3 +1930,15 @@ bool gl_image_op(backend_t *base, enum image_operations op, void *image_data,
19161930

19171931
return true;
19181932
}
1933+
1934+
enum device_status gl_device_status(backend_t *base) {
1935+
auto gd = (struct gl_data *)base;
1936+
if (!gd->has_robustness) {
1937+
return DEVICE_STATUS_NORMAL;
1938+
}
1939+
if (glGetGraphicsResetStatusARB() == GL_NO_ERROR) {
1940+
return DEVICE_STATUS_NORMAL;
1941+
} else {
1942+
return DEVICE_STATUS_RESETTING;
1943+
}
1944+
}

src/backend/gl/gl_common.h

+3
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ struct gl_data {
7575
backend_t base;
7676
// If we are using proprietary NVIDIA driver
7777
bool is_nvidia;
78+
// If ARB_robustness extension is present
79+
bool has_robustness;
7880
// Height and width of the root window
7981
int height, width;
8082
gl_win_shader_t win_shader;
@@ -133,6 +135,7 @@ void gl_fill(backend_t *base, struct color, const region_t *clip);
133135

134136
void gl_present(backend_t *base, const region_t *);
135137
bool gl_read_pixel(backend_t *base, void *image_data, int x, int y, struct color *output);
138+
enum device_status gl_device_status(backend_t *base);
136139

137140
static inline void gl_delete_texture(GLuint texture) {
138141
glDeleteTextures(1, &texture);

src/backend/gl/glx.c

+17-10
Original file line numberDiff line numberDiff line change
@@ -302,16 +302,21 @@ static backend_t *glx_init(session_t *ps) {
302302
continue;
303303
}
304304

305-
gd->ctx = glXCreateContextAttribsARB(ps->dpy, cfg[i], 0, true,
306-
(int[]){
307-
GLX_CONTEXT_MAJOR_VERSION_ARB,
308-
3,
309-
GLX_CONTEXT_MINOR_VERSION_ARB,
310-
3,
311-
GLX_CONTEXT_PROFILE_MASK_ARB,
312-
GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
313-
0,
314-
});
305+
int *attributes = (int[]){GLX_CONTEXT_MAJOR_VERSION_ARB,
306+
3,
307+
GLX_CONTEXT_MINOR_VERSION_ARB,
308+
3,
309+
GLX_CONTEXT_PROFILE_MASK_ARB,
310+
GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
311+
0,
312+
0,
313+
0};
314+
if (glxext.has_GLX_ARB_create_context_robustness) {
315+
attributes[6] = GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB;
316+
attributes[7] = GLX_LOSE_CONTEXT_ON_RESET_ARB;
317+
}
318+
319+
gd->ctx = glXCreateContextAttribsARB(ps->dpy, cfg[i], 0, true, attributes);
315320
free(cfg);
316321

317322
if (!gd->ctx) {
@@ -541,6 +546,7 @@ struct backend_operations glx_ops = {
541546
.destroy_blur_context = gl_destroy_blur_context,
542547
.get_blur_size = gl_get_blur_size,
543548
.diagnostics = glx_diagnostics,
549+
.device_status = gl_device_status,
544550
.max_buffer_age = 5, // Why?
545551
};
546552

@@ -608,6 +614,7 @@ void glxext_init(Display *dpy, int screen) {
608614
check_ext(GLX_EXT_texture_from_pixmap);
609615
check_ext(GLX_ARB_create_context);
610616
check_ext(GLX_EXT_buffer_age);
617+
check_ext(GLX_ARB_create_context_robustness);
611618
#ifdef GLX_MESA_query_renderer
612619
check_ext(GLX_MESA_query_renderer);
613620
#endif

src/backend/gl/glx.h

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ struct glxext_info {
5555
bool has_GLX_ARB_create_context;
5656
bool has_GLX_EXT_buffer_age;
5757
bool has_GLX_MESA_query_renderer;
58+
bool has_GLX_ARB_create_context_robustness;
5859
};
5960

6061
extern struct glxext_info glxext;

0 commit comments

Comments
 (0)