gl-renderer: Use helper for conversion to EGL rects
eglSwapBuffersWithDamage has to convert a damage region from Weston's global co-ordinate space, into the co-ordinate space for EGL rendering into a buffer for that output. The conversion from the global co-ordinate space in logical pixels to the output space in buffer pixels is slightly long and error-prone, involving translating by the output's offset within the global co-ordinate space, multiplying by output scale, and also translating to allow for any borders we paint around the output. After this is done, we need to flip the co-ordinates in the Y axis to account for the lower-left-origin co-ordinate space used by EGL. Since we want to reuse this for partial_update, but using a different source region, extract this conversion into a well-commented helper we can reuse. Signed-off-by: Daniel Stone <daniels@collabora.com>
This commit is contained in:
parent
a7722ee92a
commit
55bcb93fef
@ -1352,6 +1352,71 @@ output_rotate_damage(struct weston_output *output,
|
||||
go->border_damage[go->buffer_damage_index] = border_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a region in Weston's (top-left-origin) global co-ordinate space,
|
||||
* translate it to the co-ordinate space used by GL for our output
|
||||
* rendering. This requires shifting it into output co-ordinate space:
|
||||
* translating for output offset within the global co-ordinate space,
|
||||
* multiplying by output scale to get buffer rather than logical size.
|
||||
*
|
||||
* Finally, if borders are drawn around the output, we translate the area
|
||||
* to account for the border region around the outside, and add any
|
||||
* damage if the borders have been redrawn.
|
||||
*
|
||||
* @param output The output whose co-ordinate space we are after
|
||||
* @param global_region The affected region in global co-ordinate space
|
||||
* @param[out] rects Y-inverted quads in {x,y,w,h} order; caller must free
|
||||
* @param[out] nrects Number of quads (4x number of co-ordinates)
|
||||
*/
|
||||
static void
|
||||
pixman_region_to_egl_y_invert(struct weston_output *output,
|
||||
struct pixman_region32 *global_region,
|
||||
EGLint **rects,
|
||||
EGLint *nrects)
|
||||
{
|
||||
struct gl_output_state *go = get_output_state(output);
|
||||
pixman_region32_t transformed;
|
||||
struct pixman_box32 *box;
|
||||
int buffer_height;
|
||||
EGLint *d;
|
||||
int i;
|
||||
|
||||
/* Translate from global to output co-ordinate space. */
|
||||
pixman_region32_init(&transformed);
|
||||
weston_transformed_region(output->width, output->height,
|
||||
output->transform,
|
||||
output->current_scale,
|
||||
global_region, &transformed);
|
||||
|
||||
/* If we have borders drawn around the output, shift our output damage
|
||||
* to account for borders being drawn around the outside, adding any
|
||||
* damage resulting from borders being redrawn. */
|
||||
if (output_has_borders(output)) {
|
||||
pixman_region32_translate(&transformed,
|
||||
go->borders[GL_RENDERER_BORDER_LEFT].width,
|
||||
go->borders[GL_RENDERER_BORDER_TOP].height);
|
||||
output_get_border_damage(output, go->border_status,
|
||||
&transformed);
|
||||
}
|
||||
|
||||
/* Convert from a Pixman region into {x,y,w,h} quads, flipping in the
|
||||
* Y axis to account for GL's lower-left-origin co-ordinate space. */
|
||||
box = pixman_region32_rectangles(&transformed, nrects);
|
||||
*rects = malloc(*nrects * 4 * sizeof(EGLint));
|
||||
|
||||
buffer_height = go->borders[GL_RENDERER_BORDER_TOP].height +
|
||||
output->current_mode->height +
|
||||
go->borders[GL_RENDERER_BORDER_BOTTOM].height;
|
||||
|
||||
d = *rects;
|
||||
for (i = 0; i < *nrects; ++i) {
|
||||
*d++ = box[i].x1;
|
||||
*d++ = buffer_height - box[i].y2;
|
||||
*d++ = box[i].x2 - box[i].x1;
|
||||
*d++ = box[i].y2 - box[i].y1;
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTE: We now allow falling back to ARGB gl visuals when XRGB is
|
||||
* unavailable, so we're assuming the background has no transparency
|
||||
* and that everything with a blend, like drop shadows, will have something
|
||||
@ -1369,9 +1434,6 @@ gl_renderer_repaint_output(struct weston_output *output,
|
||||
struct gl_renderer *gr = get_renderer(compositor);
|
||||
EGLBoolean ret;
|
||||
static int errored;
|
||||
int i, nrects, buffer_height;
|
||||
EGLint *egl_damage, *d;
|
||||
pixman_box32_t *rects;
|
||||
pixman_region32_t buffer_damage, total_damage;
|
||||
enum gl_border_status border_damage = BORDER_STATUS_CLEAN;
|
||||
struct weston_view *view;
|
||||
@ -1448,39 +1510,18 @@ gl_renderer_repaint_output(struct weston_output *output,
|
||||
go->end_render_sync = create_render_sync(gr);
|
||||
|
||||
if (gr->swap_buffers_with_damage && !gr->fan_debug) {
|
||||
pixman_region32_init(&buffer_damage);
|
||||
weston_transformed_region(output->width, output->height,
|
||||
output->transform,
|
||||
output->current_scale,
|
||||
output_damage, &buffer_damage);
|
||||
int n_egl_rects;
|
||||
EGLint *egl_rects;
|
||||
|
||||
if (output_has_borders(output)) {
|
||||
pixman_region32_translate(&buffer_damage,
|
||||
go->borders[GL_RENDERER_BORDER_LEFT].width,
|
||||
go->borders[GL_RENDERER_BORDER_TOP].height);
|
||||
output_get_border_damage(output, go->border_status,
|
||||
&buffer_damage);
|
||||
}
|
||||
|
||||
rects = pixman_region32_rectangles(&buffer_damage, &nrects);
|
||||
egl_damage = malloc(nrects * 4 * sizeof(EGLint));
|
||||
|
||||
buffer_height = go->borders[GL_RENDERER_BORDER_TOP].height +
|
||||
output->current_mode->height +
|
||||
go->borders[GL_RENDERER_BORDER_BOTTOM].height;
|
||||
|
||||
d = egl_damage;
|
||||
for (i = 0; i < nrects; ++i) {
|
||||
*d++ = rects[i].x1;
|
||||
*d++ = buffer_height - rects[i].y2;
|
||||
*d++ = rects[i].x2 - rects[i].x1;
|
||||
*d++ = rects[i].y2 - rects[i].y1;
|
||||
}
|
||||
/* For swap_buffers_with_damage, we need to pass the region
|
||||
* which has changed since the previous SwapBuffers on this
|
||||
* surface - this is output_damage. */
|
||||
pixman_region_to_egl_y_invert(output, output_damage,
|
||||
&egl_rects, &n_egl_rects);
|
||||
ret = gr->swap_buffers_with_damage(gr->egl_display,
|
||||
go->egl_surface,
|
||||
egl_damage, nrects);
|
||||
free(egl_damage);
|
||||
pixman_region32_fini(&buffer_damage);
|
||||
egl_rects, n_egl_rects);
|
||||
free(egl_rects);
|
||||
} else {
|
||||
ret = eglSwapBuffers(gr->egl_display, go->egl_surface);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user