← recipes

Commit 6a00e03

4
plików
+414
dodanych
-1
usuniętych
@@ -0,0 +1,45 @@
1 +From: PaganDE <dev@paganlinux.org>
2 +Subject: [PATCH] gles2: fix R/B swap when reading DRM_FORMAT_BGR888
3 +
4 +GLES2 has no GL_BGR, so wlroots maps DRM_FORMAT_BGR888 to
5 +glReadPixels(GL_RGB, GL_UNSIGNED_BYTE). GL_RGB returns bytes in
6 +R,G,B order while the BGR888 layout expects B,G,R - the resulting
7 +buffer ends up with red and blue swapped.
8 +
9 +On llvmpipe the implementation read format is GL_RGB, so
10 +wlr_output_preferred_read_format() reports BGR888 and screencopy
11 +clients receive a buffer with inverted channels.
12 +
13 +Origin: PaganDE fork of wlroots 0.20.2
14 +---
15 + render/gles2/texture.c | 19 +++++++++++++++++++
16 + 1 file changed, 19 insertions(+)
17 +
18 +--- a/render/gles2/texture.c 2026-07-07 23:46:09.000000000 +0200
19 +@@ -225,6 +225,25 @@
20 + }
21 + }
22 +
23 ++ /*
24 ++ * DRM_FORMAT_BGR888 has no GLES2 equivalent: we read it as GL_RGB,
25 ++ * which returns bytes in R,G,B order, while the BGR888 layout
26 ++ * expects B,G,R. Swap the channels so the buffer actually contains
27 ++ * BGR data. Otherwise screencopy/screenshot clients see red and
28 ++ * blue swapped (visible on llvmpipe, where the preferred read
29 ++ * format is BGR888).
30 ++ */
31 ++ if (drm_fmt->drm_format == DRM_FORMAT_BGR888) {
32 ++ for (int32_t i = 0; i < src.height; ++i) {
33 ++ unsigned char *row = p + (size_t)i * options->stride;
34 ++ for (int32_t x = 0; x < src.width; ++x) {
35 ++ unsigned char tmp = row[x * 3];
36 ++ row[x * 3] = row[x * 3 + 2];
37 ++ row[x * 3 + 2] = tmp;
38 ++ }
39 ++ }
40 ++ }
41 ++
42 + wlr_egl_restore_context(&prev_ctx);
43 + pop_gles2_debug(texture->renderer);
44 +
0 45 new file mode 100644
@@ -0,0 +1,368 @@
1 +diff -ruN a/include/render/gles2.h b/include/render/gles2.h
2 +--- a/include/render/gles2.h 2026-07-07 23:46:09.000000000 +0200
3 +@@ -35,6 +35,12 @@
4 + GLint tex;
5 + GLint alpha;
6 + GLint pos_attrib;
7 ++ /* PaganDE: rounded clip */
8 ++ GLint rounded;
9 ++ GLint box_pos;
10 ++ GLint box_size;
11 ++ GLint radius;
12 ++ GLint corners;
13 + };
14 +
15 + struct wlr_gles2_renderer {
16 +diff -ruN a/include/wlr/render/pass.h b/include/wlr/render/pass.h
17 +--- a/include/wlr/render/pass.h 2026-07-07 23:46:09.000000000 +0200
18 +@@ -84,6 +84,14 @@
19 + WLR_SCALE_FILTER_NEAREST,
20 + };
21 +
22 ++/* PaganDE: rounded corners bitmask (see corner_radius below) */
23 ++enum wlr_rounded_corner {
24 ++ WLR_ROUNDED_CORNER_TOP_LEFT = 1 << 0,
25 ++ WLR_ROUNDED_CORNER_TOP_RIGHT = 1 << 1,
26 ++ WLR_ROUNDED_CORNER_BOTTOM_RIGHT = 1 << 2,
27 ++ WLR_ROUNDED_CORNER_BOTTOM_LEFT = 1 << 3,
28 ++};
29 ++
30 + struct wlr_render_texture_options {
31 + /* Source texture */
32 + struct wlr_texture *texture;
33 +@@ -95,6 +103,12 @@
34 + const float *alpha;
35 + /* Clip region, leave NULL to disable clipping */
36 + const pixman_region32_t *clip;
37 ++ /* PaganDE: rounded corners. When corner_radius > 0 and rounded_corners != 0,
38 ++ * the texture is clipped to a rectangle with rounded corners (bitmask of
39 ++ * enum wlr_rounded_corner). Renderers that do not support this feature
40 ++ * must ignore these fields. */
41 ++ float corner_radius;
42 ++ uint32_t rounded_corners;
43 + /* Transform applied to the source texture */
44 + enum wl_output_transform transform;
45 + /* Filtering */
46 +diff -ruN a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h
47 +--- a/include/wlr/types/wlr_scene.h 2026-07-07 23:46:09.000000000 +0200
48 +@@ -215,6 +215,11 @@
49 +
50 + // True if the underlying buffer is a wlr_single_pixel_buffer_v1
51 + bool is_single_pixel_buffer;
52 ++
53 ++ // PaganDE: rounded clip applied when rendering this buffer
54 ++ // (see wlr_scene_buffer_set_rounded_clip)
55 ++ float clip_radius;
56 ++ uint32_t clip_corners;
57 + // If is_single_pixel_buffer is set, contains the color of the buffer
58 + // as {R, G, B, A} where the max value of each component is UINT32_MAX
59 + uint32_t single_pixel_buffer_color[4];
60 +@@ -549,6 +554,16 @@
61 + enum wl_output_transform transform);
62 +
63 + /**
64 ++ * PaganDE: clip the buffer to a rectangle with rounded corners.
65 ++ *
66 ++ * radius is the corner radius in output pixels; corners is a bitmask of
67 ++ * enum wlr_rounded_corner. Passing radius 0 (or corners 0) disables the clip.
68 ++ * Renderers without support (e.g. pixman) ignore this.
69 ++ */
70 ++void wlr_scene_buffer_set_rounded_clip(struct wlr_scene_buffer *scene_buffer,
71 ++ float radius, uint32_t corners);
72 ++
73 ++/**
74 + * Sets the opacity of this buffer
75 + */
76 + void wlr_scene_buffer_set_opacity(struct wlr_scene_buffer *scene_buffer,
77 +diff -ruN a/render/gles2/pass.c b/render/gles2/pass.c
78 +--- a/render/gles2/pass.c 2026-07-07 23:46:09.000000000 +0200
79 +@@ -247,6 +247,19 @@
80 + set_proj_matrix(shader->proj, pass->projection_matrix, &dst_box);
81 + set_tex_matrix(shader->tex_proj, options->transform, &src_fbox);
82 +
83 ++ bool rounded = options->corner_radius > 0 && options->rounded_corners != 0;
84 ++ glUniform1f(shader->rounded, rounded ? 1.0f : 0.0f);
85 ++ if (rounded) {
86 ++ glUniform2f(shader->box_pos, dst_box.x, dst_box.y);
87 ++ glUniform2f(shader->box_size, dst_box.width, dst_box.height);
88 ++ glUniform1f(shader->radius, options->corner_radius);
89 ++ glUniform4f(shader->corners,
90 ++ (options->rounded_corners & WLR_ROUNDED_CORNER_TOP_LEFT) ? 1.0f : 0.0f,
91 ++ (options->rounded_corners & WLR_ROUNDED_CORNER_TOP_RIGHT) ? 1.0f : 0.0f,
92 ++ (options->rounded_corners & WLR_ROUNDED_CORNER_BOTTOM_RIGHT) ? 1.0f : 0.0f,
93 ++ (options->rounded_corners & WLR_ROUNDED_CORNER_BOTTOM_LEFT) ? 1.0f : 0.0f);
94 ++ }
95 ++
96 + render(&dst_box, options->clip, shader->pos_attrib);
97 +
98 + glBindTexture(texture->target, 0);
99 +diff -ruN a/render/gles2/renderer.c b/render/gles2/renderer.c
100 +--- a/render/gles2/renderer.c 2026-07-07 23:46:09.000000000 +0200
101 +@@ -652,6 +652,11 @@
102 + renderer->shaders.tex_rgba.tex = glGetUniformLocation(prog, "tex");
103 + renderer->shaders.tex_rgba.alpha = glGetUniformLocation(prog, "alpha");
104 + renderer->shaders.tex_rgba.pos_attrib = glGetAttribLocation(prog, "pos");
105 ++ renderer->shaders.tex_rgba.rounded = glGetUniformLocation(prog, "u_rounded");
106 ++ renderer->shaders.tex_rgba.box_pos = glGetUniformLocation(prog, "u_box_pos");
107 ++ renderer->shaders.tex_rgba.box_size = glGetUniformLocation(prog, "u_box_size");
108 ++ renderer->shaders.tex_rgba.radius = glGetUniformLocation(prog, "u_radius");
109 ++ renderer->shaders.tex_rgba.corners = glGetUniformLocation(prog, "u_corners");
110 +
111 + renderer->shaders.tex_rgbx.program = prog =
112 + link_program(renderer, common_vert_src, tex_rgbx_frag_src);
113 +@@ -663,6 +668,11 @@
114 + renderer->shaders.tex_rgbx.tex = glGetUniformLocation(prog, "tex");
115 + renderer->shaders.tex_rgbx.alpha = glGetUniformLocation(prog, "alpha");
116 + renderer->shaders.tex_rgbx.pos_attrib = glGetAttribLocation(prog, "pos");
117 ++ renderer->shaders.tex_rgbx.rounded = glGetUniformLocation(prog, "u_rounded");
118 ++ renderer->shaders.tex_rgbx.box_pos = glGetUniformLocation(prog, "u_box_pos");
119 ++ renderer->shaders.tex_rgbx.box_size = glGetUniformLocation(prog, "u_box_size");
120 ++ renderer->shaders.tex_rgbx.radius = glGetUniformLocation(prog, "u_radius");
121 ++ renderer->shaders.tex_rgbx.corners = glGetUniformLocation(prog, "u_corners");
122 +
123 + if (renderer->exts.OES_egl_image_external) {
124 + renderer->shaders.tex_ext.program = prog =
125 +@@ -675,6 +685,11 @@
126 + renderer->shaders.tex_ext.tex = glGetUniformLocation(prog, "tex");
127 + renderer->shaders.tex_ext.alpha = glGetUniformLocation(prog, "alpha");
128 + renderer->shaders.tex_ext.pos_attrib = glGetAttribLocation(prog, "pos");
129 ++ renderer->shaders.tex_ext.rounded = glGetUniformLocation(prog, "u_rounded");
130 ++ renderer->shaders.tex_ext.box_pos = glGetUniformLocation(prog, "u_box_pos");
131 ++ renderer->shaders.tex_ext.box_size = glGetUniformLocation(prog, "u_box_size");
132 ++ renderer->shaders.tex_ext.radius = glGetUniformLocation(prog, "u_radius");
133 ++ renderer->shaders.tex_ext.corners = glGetUniformLocation(prog, "u_corners");
134 + }
135 +
136 + pop_gles2_debug(renderer);
137 +diff -ruN a/render/gles2/shaders/tex_external.frag b/render/gles2/shaders/tex_external.frag
138 +--- a/render/gles2/shaders/tex_external.frag 2026-07-07 23:46:09.000000000 +0200
139 +@@ -10,6 +10,51 @@
140 + uniform samplerExternalOES texture0;
141 + uniform float alpha;
142 +
143 ++
144 ++// PaganDE: rounded clip (discard fragments outside the rounded rect)
145 ++// GLSL ES 1.00: tylko floaty (bez bitowych operacji); maska rogów w vec4.
146 ++uniform float u_rounded;
147 ++uniform vec2 u_box_pos;
148 ++uniform vec2 u_box_size;
149 ++uniform float u_radius;
150 ++uniform vec4 u_corners; /* x=TL y=TR z=BR w=BL, 1.0 = zaokrąglony */
151 ++
152 ++void rounded_clip() {
153 ++ if (u_rounded == 0.0) {
154 ++ return;
155 ++ }
156 ++ vec2 p = gl_FragCoord.xy - u_box_pos;
157 ++ float r = u_radius;
158 ++ /* top-left */
159 ++ if (u_corners.x > 0.5) {
160 ++ if (p.x <= r && p.y <= r && distance(p, vec2(r, r)) > r) {
161 ++ discard;
162 ++ }
163 ++ }
164 ++ /* top-right */
165 ++ if (u_corners.y > 0.5) {
166 ++ if (p.x >= u_box_size.x - r && p.y <= r
167 ++ && distance(p, vec2(u_box_size.x - r, r)) > r) {
168 ++ discard;
169 ++ }
170 ++ }
171 ++ /* bottom-right */
172 ++ if (u_corners.z > 0.5) {
173 ++ if (p.x >= u_box_size.x - r && p.y >= u_box_size.y - r
174 ++ && distance(p, vec2(u_box_size.x - r, u_box_size.y - r)) > r) {
175 ++ discard;
176 ++ }
177 ++ }
178 ++ /* bottom-left */
179 ++ if (u_corners.w > 0.5) {
180 ++ if (p.x <= r && p.y >= u_box_size.y - r
181 ++ && distance(p, vec2(r, u_box_size.y - r)) > r) {
182 ++ discard;
183 ++ }
184 ++ }
185 ++}
186 ++
187 + void main() {
188 ++ rounded_clip();
189 + gl_FragColor = texture2D(texture0, v_texcoord) * alpha;
190 + }
191 +diff -ruN a/render/gles2/shaders/tex_rgba.frag b/render/gles2/shaders/tex_rgba.frag
192 +--- a/render/gles2/shaders/tex_rgba.frag 2026-07-07 23:46:09.000000000 +0200
193 +@@ -8,6 +8,51 @@
194 + uniform sampler2D tex;
195 + uniform float alpha;
196 +
197 ++
198 ++// PaganDE: rounded clip (discard fragments outside the rounded rect)
199 ++// GLSL ES 1.00: tylko floaty (bez bitowych operacji); maska rogów w vec4.
200 ++uniform float u_rounded;
201 ++uniform vec2 u_box_pos;
202 ++uniform vec2 u_box_size;
203 ++uniform float u_radius;
204 ++uniform vec4 u_corners; /* x=TL y=TR z=BR w=BL, 1.0 = zaokrąglony */
205 ++
206 ++void rounded_clip() {
207 ++ if (u_rounded == 0.0) {
208 ++ return;
209 ++ }
210 ++ vec2 p = gl_FragCoord.xy - u_box_pos;
211 ++ float r = u_radius;
212 ++ /* top-left */
213 ++ if (u_corners.x > 0.5) {
214 ++ if (p.x <= r && p.y <= r && distance(p, vec2(r, r)) > r) {
215 ++ discard;
216 ++ }
217 ++ }
218 ++ /* top-right */
219 ++ if (u_corners.y > 0.5) {
220 ++ if (p.x >= u_box_size.x - r && p.y <= r
221 ++ && distance(p, vec2(u_box_size.x - r, r)) > r) {
222 ++ discard;
223 ++ }
224 ++ }
225 ++ /* bottom-right */
226 ++ if (u_corners.z > 0.5) {
227 ++ if (p.x >= u_box_size.x - r && p.y >= u_box_size.y - r
228 ++ && distance(p, vec2(u_box_size.x - r, u_box_size.y - r)) > r) {
229 ++ discard;
230 ++ }
231 ++ }
232 ++ /* bottom-left */
233 ++ if (u_corners.w > 0.5) {
234 ++ if (p.x <= r && p.y >= u_box_size.y - r
235 ++ && distance(p, vec2(r, u_box_size.y - r)) > r) {
236 ++ discard;
237 ++ }
238 ++ }
239 ++}
240 ++
241 + void main() {
242 ++ rounded_clip();
243 + gl_FragColor = texture2D(tex, v_texcoord) * alpha;
244 + }
245 +diff -ruN a/render/gles2/shaders/tex_rgbx.frag b/render/gles2/shaders/tex_rgbx.frag
246 +--- a/render/gles2/shaders/tex_rgbx.frag 2026-07-07 23:46:09.000000000 +0200
247 +@@ -8,6 +8,51 @@
248 + uniform sampler2D tex;
249 + uniform float alpha;
250 +
251 ++
252 ++// PaganDE: rounded clip (discard fragments outside the rounded rect)
253 ++// GLSL ES 1.00: tylko floaty (bez bitowych operacji); maska rogów w vec4.
254 ++uniform float u_rounded;
255 ++uniform vec2 u_box_pos;
256 ++uniform vec2 u_box_size;
257 ++uniform float u_radius;
258 ++uniform vec4 u_corners; /* x=TL y=TR z=BR w=BL, 1.0 = zaokrąglony */
259 ++
260 ++void rounded_clip() {
261 ++ if (u_rounded == 0.0) {
262 ++ return;
263 ++ }
264 ++ vec2 p = gl_FragCoord.xy - u_box_pos;
265 ++ float r = u_radius;
266 ++ /* top-left */
267 ++ if (u_corners.x > 0.5) {
268 ++ if (p.x <= r && p.y <= r && distance(p, vec2(r, r)) > r) {
269 ++ discard;
270 ++ }
271 ++ }
272 ++ /* top-right */
273 ++ if (u_corners.y > 0.5) {
274 ++ if (p.x >= u_box_size.x - r && p.y <= r
275 ++ && distance(p, vec2(u_box_size.x - r, r)) > r) {
276 ++ discard;
277 ++ }
278 ++ }
279 ++ /* bottom-right */
280 ++ if (u_corners.z > 0.5) {
281 ++ if (p.x >= u_box_size.x - r && p.y >= u_box_size.y - r
282 ++ && distance(p, vec2(u_box_size.x - r, u_box_size.y - r)) > r) {
283 ++ discard;
284 ++ }
285 ++ }
286 ++ /* bottom-left */
287 ++ if (u_corners.w > 0.5) {
288 ++ if (p.x <= r && p.y >= u_box_size.y - r
289 ++ && distance(p, vec2(r, u_box_size.y - r)) > r) {
290 ++ discard;
291 ++ }
292 ++ }
293 ++}
294 ++
295 + void main() {
296 ++ rounded_clip();
297 + gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0) * alpha;
298 + }
299 +diff -ruN a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c
300 +--- a/types/scene/wlr_scene.c 2026-07-07 23:46:09.000000000 +0200
301 +@@ -1124,6 +1124,18 @@
302 + }
303 + }
304 +
305 ++void wlr_scene_buffer_set_rounded_clip(struct wlr_scene_buffer *scene_buffer,
306 ++ float radius, uint32_t corners) {
307 ++ if (scene_buffer->clip_radius == radius
308 ++ && scene_buffer->clip_corners == corners) {
309 ++ return;
310 ++ }
311 ++ assert(radius >= 0);
312 ++ scene_buffer->clip_radius = radius;
313 ++ scene_buffer->clip_corners = corners;
314 ++ scene_node_update(&scene_buffer->node, NULL);
315 ++}
316 ++
317 + void wlr_scene_buffer_set_opacity(struct wlr_scene_buffer *scene_buffer,
318 + float opacity) {
319 + if (scene_buffer->opacity == opacity) {
320 +@@ -1499,6 +1511,26 @@
321 + case WLR_SCENE_NODE_BUFFER:;
322 + struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node);
323 +
324 ++ bool rounded = scene_buffer->clip_radius > 0
325 ++ && scene_buffer->clip_corners != 0;
326 ++ if (rounded) {
327 ++ /* Corner areas are no longer opaque: exclude them from the
328 ++ * opaque region so occlusion and blending stay correct. */
329 ++ int r = (int)scene_buffer->clip_radius;
330 ++ pixman_region32_t corners;
331 ++ pixman_region32_init(&corners);
332 ++ pixman_region32_union_rect(&corners, &corners,
333 ++ x, y, r, r);
334 ++ pixman_region32_union_rect(&corners, &corners,
335 ++ x + dst_box.width - r, y, r, r);
336 ++ pixman_region32_union_rect(&corners, &corners,
337 ++ x + dst_box.width - r, y + dst_box.height - r, r, r);
338 ++ pixman_region32_union_rect(&corners, &corners,
339 ++ x, y + dst_box.height - r, r, r);
340 ++ pixman_region32_subtract(&opaque, &opaque, &corners);
341 ++ pixman_region32_fini(&corners);
342 ++ }
343 ++
344 + if (scene_buffer->is_single_pixel_buffer) {
345 + // Render the buffer as a rect, this is likely to be more efficient
346 + wlr_render_pass_add_rect(data->render_pass, &(struct wlr_render_rect_options){
347 +@@ -1544,9 +1576,11 @@
348 + .dst_box = dst_box,
349 + .transform = transform,
350 + .clip = &render_region,
351 ++ .corner_radius = scene_buffer->clip_radius,
352 ++ .rounded_corners = scene_buffer->clip_corners,
353 + .alpha = &scene_buffer->opacity,
354 + .filter_mode = scene_buffer->filter_mode,
355 +- .blend_mode = !data->output->scene->calculate_visibility ||
356 ++ .blend_mode = rounded || !data->output->scene->calculate_visibility ||
357 + !pixman_region32_empty(&opaque) ?
358 + WLR_RENDER_BLEND_MODE_PREMULTIPLIED : WLR_RENDER_BLEND_MODE_NONE,
359 + .transfer_function = scene_buffer->transfer_function,
@@ -1,5 +1,5 @@
1 1 pkgname: kernel
2 -pkgver: '7.2.3'
2 +pkgver: '7.2.5'
3 3 pkgrel: '1'
4 4 pkgdesc: 'Pagan Linux kernel (rolling) – strojenie identyczne z ISO buildera (CONFIG_LOCALVERSION=-pagan, wbudowane squashfs/exFAT/NVMe/USB).'
5 5 url: 'https://www.kernel.org'