summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoïc Molinari <loic.molinari@collabora.com>2023-08-30 16:20:52 +0200
committerMarius Vlad <marius.vlad0@gmail.com>2024-03-05 11:48:17 +0000
commit2170caade07c6c26115faed20d54599d24937fa0 (patch)
tree385a38e342bc7cf1f0dda477fce0f3578513e7bf
parent2d71347397fded24b88c0131513f7450ca18a997 (diff)
gl-renderer: Compress damage rects once per paint node
Before rendering a surface, its visible region is intersected with the damage region in global space. The resulting region is compressed (first step) and transformed to surface space (second step) for clipping. These steps sometimes happen twice when a paint node both has an opaque and a translucent region. This commit makes sure the first step happens just once. Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
-rw-r--r--libweston/renderer-gl/gl-renderer.c105
1 files changed, 66 insertions, 39 deletions
diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c
index e1257c66..a052f768 100644
--- a/libweston/renderer-gl/gl-renderer.c
+++ b/libweston/renderer-gl/gl-renderer.c
@@ -471,51 +471,41 @@ timeline_submit_render_sync(struct gl_renderer *gr,
wl_list_insert(&go->timeline_render_point_list, &trp->link);
}
-static int
-compress_bands(pixman_box32_t *inrects, int nrects, pixman_box32_t **outrects);
-
static void
global_to_surface(pixman_box32_t *rect, struct weston_view *ev,
struct clipper_vertex polygon[4], bool *axis_aligned);
static int
texture_region(struct weston_paint_node *pnode,
- pixman_region32_t *region,
- pixman_region32_t *surf_region)
+ pixman_box32_t *damage_rects,
+ int damage_nrects,
+ pixman_region32_t *surface_region)
{
struct weston_compositor *ec = pnode->surface->compositor;
struct weston_view *ev = pnode->view;
struct gl_renderer *gr = get_renderer(ec);
struct clipper_vertex *v;
unsigned int *vtxcnt, nvtx = 0;
- pixman_box32_t *rects, *surf_rects;
- pixman_box32_t *raw_rects;
- int i, j, nrects, nsurf, raw_nrects;
- bool used_band_compression, axis_aligned;
+ pixman_box32_t *surface_rects;
+ int i, j, surface_nrects, nfans;
+ bool axis_aligned;
struct clipper_vertex polygon[4];
struct clipper_quad quad;
- raw_rects = pixman_region32_rectangles(region, &raw_nrects);
- surf_rects = pixman_region32_rectangles(surf_region, &nsurf);
+ surface_rects = pixman_region32_rectangles(surface_region,
+ &surface_nrects);
- if (raw_nrects < 4) {
- used_band_compression = false;
- nrects = raw_nrects;
- rects = raw_rects;
- } else {
- nrects = compress_bands(raw_rects, raw_nrects, &rects);
- used_band_compression = true;
- }
/* worst case we can have 8 vertices per rect (ie. clipped into
* an octagon):
*/
- v = wl_array_add(&gr->vertices, nrects * nsurf * 8 * sizeof *v);
- vtxcnt = wl_array_add(&gr->vtxcnt, nrects * nsurf * sizeof *vtxcnt);
+ nfans = damage_nrects * surface_nrects;
+ v = wl_array_add(&gr->vertices, nfans * 8 * sizeof *v);
+ vtxcnt = wl_array_add(&gr->vtxcnt, nfans * sizeof *vtxcnt);
- for (i = 0; i < nrects; i++) {
- global_to_surface(&rects[i], ev, polygon, &axis_aligned);
+ for (i = 0; i < damage_nrects; i++) {
+ global_to_surface(&damage_rects[i], ev, polygon, &axis_aligned);
clipper_quad_init(&quad, polygon, axis_aligned);
- for (j = 0; j < nsurf; j++) {
+ for (j = 0; j < surface_nrects; j++) {
int n;
/* The transformed quad, after clipping to the surface rect, can
@@ -531,7 +521,7 @@ texture_region(struct weston_paint_node *pnode,
* To do this, we first calculate the (up to eight) points at the
* intersection of the edges of the quad and the surface rect.
*/
- n = clipper_quad_clip_box32(&quad, &surf_rects[j], v);
+ n = clipper_quad_clip_box32(&quad, &surface_rects[j], v);
if (n >= 3) {
v += n;
vtxcnt[nvtx++] = n;
@@ -539,8 +529,6 @@ texture_region(struct weston_paint_node *pnode,
}
}
- if (used_band_compression)
- free(rects);
return nvtx;
}
@@ -939,8 +927,9 @@ triangle_fan_debug(struct gl_renderer *gr,
static void
repaint_region(struct gl_renderer *gr,
struct weston_paint_node *pnode,
- pixman_region32_t *region,
- pixman_region32_t *surf_region,
+ pixman_box32_t *damage_rects,
+ int damage_nrects,
+ pixman_region32_t *surface_region,
const struct gl_shader_config *sconf)
{
struct weston_output *output = pnode->output;
@@ -948,15 +937,16 @@ repaint_region(struct gl_renderer *gr,
unsigned int *vtxcnt;
int i, first, nfans;
- /* The final region to be painted is the intersection of
- * 'region' and 'surf_region'. However, 'region' is in the global
- * coordinates, and 'surf_region' is in the surface-local
- * coordinates. texture_region() will iterate over all pairs of
- * rectangles from both regions, compute the intersection
- * polygon for each pair, and store it as a triangle fan if
- * it has a non-zero area (at least 3 vertices, actually).
+ /* The final region to be painted is the intersection of the damage
+ * rects and the surface region. However, damage rects are in global
+ * coordinates and surface region is in surface coordinates.
+ * texture_region() will iterate over all pairs of rectangles from both
+ * regions, compute the intersection polygon for each pair, and store it
+ * as a triangle fan if it has a non-zero area (at least 3 vertices,
+ * actually).
*/
- nfans = texture_region(pnode, region, surf_region);
+ nfans = texture_region(pnode, damage_rects, damage_nrects,
+ surface_region);
v = gr->vertices.data;
vtxcnt = gr->vtxcnt.data;
@@ -1269,6 +1259,34 @@ global_to_surface(pixman_box32_t *rect, struct weston_view *ev,
(ev->transform.matrix.type < WESTON_MATRIX_TRANSFORM_ROTATE);
}
+/* Transform damage rects of 'region'. 'rects', 'nrects' and 'free' are output
+ * arguments set if 'rects' is NULL. Caller must free 'rects' if 'free' is true
+ * on return.
+ */
+static void
+transform_damage(pixman_region32_t *region,
+ pixman_box32_t **rects,
+ int *nrects,
+ bool *free)
+{
+ pixman_box32_t *damage_rects;
+ int damage_nrects;
+
+ if (*rects)
+ return;
+
+ damage_rects = pixman_region32_rectangles(region, &damage_nrects);
+
+ if (damage_nrects < 4) {
+ *rects = damage_rects;
+ *nrects = damage_nrects;
+ *free = false;
+ } else {
+ *nrects = compress_bands(damage_rects, damage_nrects, rects);
+ *free = true;
+ }
+}
+
static void
draw_paint_node(struct weston_paint_node *pnode,
pixman_region32_t *damage /* in global coordinates */)
@@ -1285,6 +1303,9 @@ draw_paint_node(struct weston_paint_node *pnode,
pixman_region32_t surface_blend;
GLint filter;
struct gl_shader_config sconf;
+ pixman_box32_t *rects = NULL;
+ bool free_rects = false;
+ int nrects;
if (gb->shader_variant == SHADER_VARIANT_NONE &&
!buffer->direct_display)
@@ -1344,16 +1365,22 @@ draw_paint_node(struct weston_paint_node *pnode,
else
glDisable(GL_BLEND);
- repaint_region(gr, pnode, &repaint, &surface_opaque, &alt);
+ transform_damage(&repaint, &rects, &nrects, &free_rects);
+ repaint_region(gr, pnode, rects, nrects, &surface_opaque, &alt);
gs->used_in_output_repaint = true;
}
if (pixman_region32_not_empty(&surface_blend)) {
glEnable(GL_BLEND);
- repaint_region(gr, pnode, &repaint, &surface_blend, &sconf);
+
+ transform_damage(&repaint, &rects, &nrects, &free_rects);
+ repaint_region(gr, pnode, rects, nrects, &surface_blend, &sconf);
gs->used_in_output_repaint = true;
}
+ if (free_rects)
+ free(rects);
+
pixman_region32_fini(&surface_blend);
pixman_region32_fini(&surface_opaque);