libweston: Enforce renderbuffer size

Although backends can create renderbuffers of any size, they always
request the output's current mode size (including decorations).
Letting backends ask for a different size than the output has a few
read-back related design issues like for instance weston_renderer's
read_pixels() API users, currently assuming the output size and
without knowledge of renderbuffers, can retrieve cropped images if a
backend asks for a smaller size. Same issue for the output capture
subsystem.

This commit proposes to fix these issues by simply, albeit perhaps
radically, removing the width and height parameters from
create_renderbuffer(), enforcing the current mode's size of the
associated output.

The VNC and PipeWire backends now also access the output size via the
current mode, not through the width and height variables. This has the
benefit of unifying the backends, as well as the renderers, in their
use of output sizes.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
This commit is contained in:
Loïc Molinari 2024-08-09 14:39:32 +02:00
parent 4eddce5557
commit 96c49d91a5
10 changed files with 55 additions and 64 deletions

View file

@ -1607,7 +1607,7 @@ drm_rb_discarded_cb(weston_renderbuffer_t rb, void *data)
if (!dumb)
break;
rb = renderer->create_renderbuffer(&output->base, pfmt,
w, h, dumb->map,
dumb->map,
dumb->strides[0],
drm_rb_discarded_cb,
output);
@ -1663,7 +1663,7 @@ drm_output_init_pixman(struct drm_output *output, struct drm_backend *b)
output->renderbuffer[i] =
renderer->create_renderbuffer(&output->base,
options.format, w, h,
options.format,
output->dumb[i]->map,
output->dumb[i]->strides[0],
drm_rb_discarded_cb,

View file

@ -302,8 +302,6 @@ headless_output_enable_gl(struct headless_output *output)
output->renderbuffer =
renderer->create_renderbuffer(&output->base, b->formats[0],
options.fb_size.width,
options.fb_size.height,
NULL, 0, NULL, NULL);
if (!output->renderbuffer)
goto err_renderbuffer;
@ -334,8 +332,6 @@ headless_output_enable_pixman(struct headless_output *output)
output->renderbuffer =
renderer->create_renderbuffer(&output->base, options.format,
output->base.current_mode->width,
output->base.current_mode->height,
NULL, 0, NULL, NULL);
if (!output->renderbuffer)
goto err_renderer;

View file

@ -266,14 +266,16 @@ pipewire_output_connect(struct pipewire_output *output)
/* TODO: Add support for modifier discovery and negotiation. */
uint64_t modifier[] = { DRM_FORMAT_MOD_LINEAR };
params[i++] = spa_pod_build_format(&builder,
output->base.width, output->base.height,
output->base.current_mode->width,
output->base.current_mode->height,
output->base.current_mode->refresh / 1000,
output->pixel_format->format,
modifier);
}
params[i++] = spa_pod_build_format(&builder,
output->base.width, output->base.height,
output->base.current_mode->width,
output->base.current_mode->height,
output->base.current_mode->refresh / 1000,
output->pixel_format->format, NULL);
@ -307,8 +309,8 @@ pipewire_output_enable_pixman(struct pipewire_output *output)
const struct pixman_renderer_output_options options = {
.use_shadow = true,
.fb_size = {
.width = output->base.width,
.height = output->base.height,
.width = output->base.current_mode->width,
.height = output->base.current_mode->height,
},
.format = output->pixel_format,
};
@ -490,8 +492,8 @@ pipewire_output_create_dmabuf(struct pipewire_output *output)
uint64_t modifier[] = { DRM_FORMAT_MOD_LINEAR };
format = output->pixel_format;
width = output->base.width;
height = output->base.height;
width = output->base.current_mode->width;
height = output->base.current_mode->height;
linux_dmabuf_memory = renderer->dmabuf_alloc(renderer, width, height,
format->format,
@ -612,8 +614,8 @@ pipewire_output_create_memfd(struct pipewire_output *output)
memfd = xzalloc(sizeof *memfd);
format = output->pixel_format;
width = output->base.width;
height = output->base.height;
width = output->base.current_mode->width;
height = output->base.current_mode->height;
stride = width * format->bpp / 8;
size = height * stride;
@ -710,9 +712,7 @@ pipewire_output_stream_add_buffer(void *data, struct pw_buffer *buffer)
frame_data->dmabuf = dmabuf;
} else if (buffertype & (1u << SPA_DATA_MemFd)) {
const struct pixel_format_info *format = output->pixel_format;
int width = output->base.width;
int height = output->base.height;
int stride = width * format->bpp / 8;
int stride = output->base.current_mode->width * format->bpp / 8;
struct pipewire_memfd *memfd;
memfd = pipewire_output_create_memfd(output);
@ -725,8 +725,8 @@ pipewire_output_stream_add_buffer(void *data, struct pw_buffer *buffer)
frame_data->renderbuffer =
renderer->create_renderbuffer(&output->base, format,
width, height, d[0].data,
stride, NULL, NULL);
d[0].data, stride, NULL,
NULL);
frame_data->memfd = memfd;
}
}
@ -904,7 +904,7 @@ pipewire_submit_buffer(struct pipewire_output *output,
if (dmabuf)
stride = dmabuf->linux_dmabuf_memory->attributes->stride[0];
else
stride = output->base.width * pixel_format->bpp / 8;
stride = output->base.current_mode->width * pixel_format->bpp / 8;
size = output->base.height * stride;
spa_buffer = buffer->buffer;

View file

@ -435,8 +435,6 @@ rdp_buffer_create(struct rdp_output *output)
buffer = xmalloc(sizeof *buffer);
rb = rdr->create_renderbuffer(&output->base, format,
output->base.current_mode->width,
output->base.current_mode->height,
pixman_image_get_data(shadow_surface),
output->base.current_mode->width * 4,
rdp_rb_discarded_cb, buffer);

View file

@ -698,10 +698,8 @@ vnc_buffer_create(struct nvnc_fb* fb, struct vnc_output *output)
struct vnc_buffer *buffer = xmalloc(sizeof *buffer);
buffer->rb = rdr->create_renderbuffer(&output->base, pfmt,
output->base.width,
output->base.height,
nvnc_fb_get_addr(fb),
output->base.width * 4,
output->base.current_mode->width * 4,
vnc_rb_discarded_cb, buffer);
buffer->fb = fb;
buffer->output = output;
@ -822,8 +820,8 @@ vnc_output_enable(struct weston_output *base)
case WESTON_RENDERER_PIXMAN: {
const struct pixman_renderer_output_options options = {
.fb_size = {
.width = output->base.width,
.height = output->base.height,
.width = output->base.current_mode->width,
.height = output->base.current_mode->height,
},
.format = backend->formats[0],
};
@ -834,12 +832,12 @@ vnc_output_enable(struct weston_output *base)
case WESTON_RENDERER_GL: {
const struct gl_renderer_fbo_options options = {
.area = {
.width = output->base.width,
.height = output->base.height,
.width = output->base.current_mode->width,
.height = output->base.current_mode->height,
},
.fb_size = {
.width = output->base.width,
.height = output->base.height,
.width = output->base.current_mode->width,
.height = output->base.current_mode->height,
},
};
if (renderer->gl->output_fbo_create(&output->base, &options) < 0)
@ -855,10 +853,10 @@ vnc_output_enable(struct weston_output *base)
finish_frame_handler,
output);
output->fb_pool = nvnc_fb_pool_new(output->base.width,
output->base.height,
output->fb_pool = nvnc_fb_pool_new(output->base.current_mode->width,
output->base.current_mode->height,
backend->formats[0]->format,
output->base.width);
output->base.current_mode->width);
output->display = nvnc_display_new(0, 0);

View file

@ -404,11 +404,11 @@ wayland_output_get_shm_buffer(struct wayland_output *output)
if (output->frame) {
frame_interior(output->frame, &area.x, &area.y,
&area.width, &area.height);
assert(area.width == output->base.current_mode->width);
assert(area.height == output->base.current_mode->height);
} else {
area.x = 0;
area.y = 0;
area.width = output->base.current_mode->width;
area.height = output->base.current_mode->height;
}
renderer = b->compositor->renderer;
@ -417,7 +417,6 @@ wayland_output_get_shm_buffer(struct wayland_output *output)
if (renderer->type == WESTON_RENDERER_PIXMAN)
sb->renderbuffer =
renderer->create_renderbuffer(&output->base, pfmt,
area.width, area.height,
(uint32_t *)(data + area.y * stride) + area.x,
stride,
wayland_rb_discarded_cb,

View file

@ -170,8 +170,7 @@ x11_output_destroy(struct weston_output *base);
static int
x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
const struct pixel_format_info *pfmt, int width,
int height);
const struct pixel_format_info *pfmt);
static inline struct x11_output *
to_x11_output(struct weston_output *base)
@ -809,9 +808,7 @@ x11_rb_discarded_cb(weston_renderbuffer_t rb, void *data)
pfmt = x11_output_get_shm_pixel_format(output);
if (!pfmt)
return false;
if (x11_output_init_shm(output->backend, output, pfmt,
output->base.current_mode->width,
output->base.current_mode->height) < 0) {
if (x11_output_init_shm(output->backend, output, pfmt) < 0) {
weston_log("Failed to initialize SHM for the X11 output\n");
return false;
}
@ -822,15 +819,18 @@ x11_rb_discarded_cb(weston_renderbuffer_t rb, void *data)
static int
x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
const struct pixel_format_info *pfmt, int width, int height)
const struct pixel_format_info *pfmt)
{
struct weston_renderer *renderer = output->base.compositor->renderer;
int bitsperpixel = pfmt->bpp;
size_t size = output->base.current_mode->width *
output->base.current_mode->height * (bitsperpixel / 8);
int stride = output->base.current_mode->width * (bitsperpixel / 8);
xcb_void_cookie_t cookie;
xcb_generic_error_t *err;
/* Create SHM segment and attach it */
output->shm_id = shmget(IPC_PRIVATE, width * height * (bitsperpixel / 8), IPC_CREAT | S_IRWXU);
output->shm_id = shmget(IPC_PRIVATE, size, IPC_CREAT | S_IRWXU);
if (output->shm_id == -1) {
weston_log("x11shm: failed to allocate SHM segment\n");
return -1;
@ -854,10 +854,9 @@ x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
/* Now create pixman image */
output->renderbuffer =
renderer->create_renderbuffer(&output->base, pfmt, width,
height, output->buf,
width * (bitsperpixel / 8),
x11_rb_discarded_cb, output);
renderer->create_renderbuffer(&output->base, pfmt, output->buf,
stride, x11_rb_discarded_cb,
output);
output->gc = xcb_generate_id(b->conn);
xcb_create_gc(b->conn, output->gc, output->window, 0, NULL);
@ -1083,8 +1082,7 @@ x11_output_enable(struct weston_output *base)
weston_log("Failed to create pixman renderer for output\n");
goto err;
}
if (x11_output_init_shm(b, output, options.format,
mode->width, mode->height) < 0) {
if (x11_output_init_shm(b, output, options.format) < 0) {
weston_log("Failed to initialize SHM for the X11 output\n");
renderer->pixman->output_destroy(&output->base);
goto err;

View file

@ -118,8 +118,6 @@ struct weston_renderer {
*
* \param output The output to render.
* \param format The renderbuffer pixel format.
* \param width The renderbuffer width.
* \param height The renderbuffer height.
* \param buffer The destination buffer, or \c NULL.
* \param stride The destination \c buffer stride in bytes, or 0.
* \param discarded_cb The callback emitted on a discarded event, or
@ -129,7 +127,8 @@ struct weston_renderer {
*
* This function creates a renderbuffer of the requested format. The
* renderer can then use it to repaint the \c output into the specified
* destination \c buffer, or into an internal buffer if \c NULL.
* destination \c buffer, which must be the same size as the \c output
* (including borders), or into an internal buffer if \c NULL.
*
* Backends should provide a \c discarded_cb callback in order to
* properly handle renderbuffer lifetime.
@ -139,8 +138,6 @@ struct weston_renderer {
weston_renderbuffer_t
(*create_renderbuffer)(struct weston_output *output,
const struct pixel_format_info *format,
int width,
int height,
void *buffer,
int stride,
weston_renderbuffer_discarded_func discarded_cb,
@ -158,7 +155,8 @@ struct weston_renderer {
*
* This function creates a renderbuffer from a DMABUF. The renderer can
* then use it to repaint the output into the specified destination \c
* dmabuf.
* dmabuf, which must be the same size as the \c output (including
* borders).
*
* Backends should provide a \c discarded_cb callback in order to
* properly handle renderbuffer lifetime.

View file

@ -920,8 +920,7 @@ pixman_renderer_surface_copy_content(struct weston_surface *surface,
static weston_renderbuffer_t
pixman_renderer_create_renderbuffer(struct weston_output *output,
const struct pixel_format_info *format,
int width, int height, void *buffer,
int stride,
void *buffer, int stride,
weston_renderbuffer_discarded_func discarded_cb,
void *user_data)
{
@ -934,13 +933,16 @@ pixman_renderer_create_renderbuffer(struct weston_output *output,
if (buffer)
renderbuffer->image =
pixman_image_create_bits(format->pixman_format, width,
height, buffer, stride);
pixman_image_create_bits(format->pixman_format,
output->current_mode->width,
output->current_mode->height,
buffer, stride);
else
renderbuffer->image =
pixman_image_create_bits_no_clear(format->pixman_format,
width, height, NULL,
0);
output->current_mode->width,
output->current_mode->height,
NULL, 0);
if (!renderbuffer->image) {
free(renderbuffer);

View file

@ -871,10 +871,11 @@ gl_renderer_create_renderbuffer_dummy(struct weston_output *output)
static weston_renderbuffer_t
gl_renderer_create_renderbuffer(struct weston_output *output,
const struct pixel_format_info *format,
int width, int height, void *buffer, int stride,
void *buffer, int stride,
weston_renderbuffer_discarded_func discarded_cb,
void *user_data)
{
struct gl_output_state *go = get_output_state(output);
struct gl_renderer *gr = get_renderer(output->compositor);
struct gl_renderbuffer *renderbuffer;
GLuint fb, rb;
@ -896,7 +897,8 @@ gl_renderer_create_renderbuffer(struct weston_output *output,
return NULL;
}
if (!gl_fbo_init(format->gl_internalformat, width, height, &fb, &rb)) {
if (!gl_fbo_init(format->gl_internalformat, go->fb_size.width,
go->fb_size.height, &fb, &rb)) {
weston_log("Failed to init renderbuffer%s\n",
buffer ? " from buffer" : "");
return NULL;