Skip to content
Commits on Source (9)
......@@ -236,6 +236,7 @@ create_gbm_surface(struct gbm_device *gbm, struct drm_output *output)
int
drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
{
const struct weston_mode *mode = output->base.current_mode;
uint32_t format[2] = {
output->gbm_format,
fallback_format_for(output->gbm_format),
......@@ -243,6 +244,12 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
struct gl_renderer_output_options options = {
.drm_formats = format,
.drm_formats_count = 1,
.area.x = 0,
.area.y = 0,
.area.width = mode->width,
.area.height = mode->height,
.fb_size.width = mode->width,
.fb_size.height = mode->height,
};
assert(output->gbm_surface == NULL);
......
......@@ -1186,6 +1186,7 @@ drm_output_init_pixman(struct drm_output *output, struct drm_backend *b)
unsigned int i;
const struct pixman_renderer_output_options options = {
.use_shadow = b->use_pixman_shadow,
.fb_size = { .width = w, .height = h },
};
switch (format) {
......
......@@ -214,11 +214,16 @@ headless_output_enable_gl(struct headless_output *output)
{
struct weston_compositor *compositor = output->base.compositor;
struct headless_backend *b = to_headless_backend(compositor);
const struct weston_mode *mode = output->base.current_mode;
const struct gl_renderer_pbuffer_options options = {
.width = output->base.current_mode->width,
.height = output->base.current_mode->height,
.drm_formats = headless_formats,
.drm_formats_count = ARRAY_LENGTH(headless_formats),
.area.x = 0,
.area.y = 0,
.area.width = mode->width,
.area.height = mode->height,
.fb_size.width = mode->width,
.fb_size.height = mode->height,
};
if (b->glri->output_pbuffer_create(&output->base, &options) < 0) {
......@@ -235,6 +240,10 @@ headless_output_enable_pixman(struct headless_output *output)
const struct pixel_format_info *pfmt;
const struct pixman_renderer_output_options options = {
.use_shadow = true,
.fb_size = {
.width = output->base.current_mode->width,
.height = output->base.current_mode->height
},
};
pfmt = pixel_format_get_info(headless_formats[0]);
......
......@@ -345,7 +345,6 @@ rdp_switch_mode(struct weston_output *output, struct weston_mode *target_mode)
rdpSettings *settings;
pixman_image_t *new_shadow_buffer;
struct weston_mode *local_mode;
const struct pixman_renderer_output_options options = { .use_shadow = true, };
assert(output);
......@@ -363,8 +362,9 @@ rdp_switch_mode(struct weston_output *output, struct weston_mode *target_mode)
output->current_mode = local_mode;
output->current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
pixman_renderer_output_destroy(output);
pixman_renderer_output_create(output, &options);
weston_renderer_resize_output(output, &(struct weston_size){
.width = output->current_mode->width,
.height = output->current_mode->height }, NULL);
new_shadow_buffer = pixman_image_create_bits(PIXMAN_x8r8g8b8, target_mode->width,
target_mode->height, 0, target_mode->width * 4);
......@@ -442,6 +442,10 @@ rdp_output_enable(struct weston_output *base)
struct wl_event_loop *loop;
const struct pixman_renderer_output_options options = {
.use_shadow = true,
.fb_size = {
.width = output->base.current_mode->width,
.height = output->base.current_mode->height
},
};
assert(output);
......
......@@ -783,23 +783,30 @@ wayland_output_destroy(struct weston_output *base)
static int
wayland_output_init_gl_renderer(struct wayland_output *output)
{
int32_t fwidth = 0, fheight = 0;
const struct weston_mode *mode = output->base.current_mode;
struct gl_renderer_output_options options = {
.drm_formats = wayland_formats,
.drm_formats_count = ARRAY_LENGTH(wayland_formats),
};
if (output->frame) {
fwidth = frame_width(output->frame);
fheight = frame_height(output->frame);
frame_interior(output->frame, &options.area.x, &options.area.y,
&options.area.width, &options.area.height);
options.fb_size.width = frame_width(output->frame);
options.fb_size.height = frame_height(output->frame);
} else {
fwidth = output->base.current_mode->width;
fheight = output->base.current_mode->height;
options.area.x = 0;
options.area.y = 0;
options.area.width = mode->width;
options.area.height = mode->height;
options.fb_size.width = mode->width;
options.fb_size.height = mode->height;
}
output->gl.egl_window =
wl_egl_window_create(output->parent.surface,
fwidth, fheight);
options.fb_size.width,
options.fb_size.height);
if (!output->gl.egl_window) {
weston_log("failure to create wl_egl_window\n");
return -1;
......@@ -823,6 +830,10 @@ wayland_output_init_pixman_renderer(struct wayland_output *output)
{
const struct pixman_renderer_output_options options = {
.use_shadow = true,
.fb_size = {
.width = output->base.current_mode->width,
.height = output->base.current_mode->height
},
};
return pixman_renderer_output_create(&output->base, &options);
}
......@@ -878,6 +889,7 @@ wayland_output_resize_surface(struct wayland_output *output)
if (output->gl.egl_window) {
wl_egl_window_resize(output->gl.egl_window,
fb_size.width, fb_size.height, 0, 0);
weston_renderer_resize_output(&output->base, &fb_size, &area);
/* These will need to be re-created due to the resize */
gl_renderer->output_set_border(&output->base,
......@@ -900,8 +912,19 @@ wayland_output_resize_surface(struct wayland_output *output)
0, 0, 0, NULL);
cairo_surface_destroy(output->gl.border.bottom);
output->gl.border.bottom = NULL;
}
} else
#endif
{
/*
* Pixman-renderer never knows about decorations, we blit them
* ourselves.
*/
struct weston_size pm_size = {
.width = area.width,
.height = area.height
};
weston_renderer_resize_output(&output->base, &pm_size, NULL);
}
wayland_output_destroy_shm_buffers(output);
}
......
......@@ -824,8 +824,8 @@ x11_output_switch_mode(struct weston_output *base, struct weston_mode *mode)
{
struct x11_backend *b;
struct x11_output *output = to_x11_output(base);
struct weston_size fb_size;
static uint32_t values[2];
int ret;
assert(output);
......@@ -853,42 +853,18 @@ x11_output_switch_mode(struct weston_output *base, struct weston_mode *mode)
XCB_CONFIG_WINDOW_HEIGHT, values);
}
output->mode.width = mode->width;
output->mode.height = mode->height;
fb_size.width = output->mode.width = mode->width;
fb_size.height = output->mode.height = mode->height;
weston_renderer_resize_output(&output->base, &fb_size, NULL);
if (b->use_pixman) {
const struct pixman_renderer_output_options options = {
.use_shadow = true,
};
pixman_renderer_output_destroy(&output->base);
x11_output_deinit_shm(b, output);
if (x11_output_init_shm(b, output,
output->base.current_mode->width,
output->base.current_mode->height) < 0) {
fb_size.width, fb_size.height) < 0) {
weston_log("Failed to initialize SHM for the X11 output\n");
return -1;
}
if (pixman_renderer_output_create(&output->base, &options) < 0) {
weston_log("Failed to create pixman renderer for output\n");
x11_output_deinit_shm(b, output);
return -1;
}
} else {
Window xid = (Window) output->window;
const struct gl_renderer_output_options options = {
.window_for_legacy = (EGLNativeWindowType) (uintptr_t) output->window,
.window_for_platform = &xid,
.drm_formats = x11_formats,
.drm_formats_count = ARRAY_LENGTH(x11_formats),
};
gl_renderer->output_destroy(&output->base);
ret = gl_renderer->output_window_create(&output->base, &options);
if (ret < 0)
return -1;
}
output->resize_pending = false;
......@@ -1049,6 +1025,10 @@ x11_output_enable(struct weston_output *base)
if (b->use_pixman) {
const struct pixman_renderer_output_options options = {
.use_shadow = true,
.fb_size = {
.width = mode->width,
.height = mode->height
},
};
if (x11_output_init_shm(b, output,
mode->width, mode->height) < 0) {
......@@ -1071,6 +1051,12 @@ x11_output_enable(struct weston_output *base)
.window_for_platform = &xid,
.drm_formats = x11_formats,
.drm_formats_count = ARRAY_LENGTH(x11_formats),
.area.x = 0,
.area.y = 0,
.area.width = mode->width,
.area.height = mode->height,
.fb_size.width = mode->width,
.fb_size.height = mode->height,
};
ret = gl_renderer->output_window_create(&output->base,
......
......@@ -8865,3 +8865,30 @@ weston_output_disable_planes_decr(struct weston_output *output)
weston_schedule_surface_protection_update(output->compositor);
}
/** Tell the renderer that the target framebuffer size has changed
*
* \param output The output that was resized.
* \param fb_size The framebuffer size, including output decorations.
* \param area The composited area inside the framebuffer, excluding
* decorations. This can also be NULL, which means the whole fb_size is
* the composited area.
*/
WL_EXPORT void
weston_renderer_resize_output(struct weston_output *output,
const struct weston_size *fb_size,
const struct weston_geometry *area)
{
struct weston_renderer *r = output->compositor->renderer;
struct weston_geometry def = {
.x = 0,
.y = 0,
.width = fb_size->width,
.height = fb_size->height
};
if (!r->resize_output(output, fb_size, area ?: &def)) {
weston_log("Error: Resizing output '%s' failed.\n",
output->name);
}
}
......@@ -41,6 +41,7 @@
*/
#include <libweston/libweston.h>
#include <assert.h>
#include "color.h"
/* compositor <-> renderer interface */
......@@ -52,6 +53,15 @@ struct weston_renderer {
uint32_t width, uint32_t height);
void (*repaint_output)(struct weston_output *output,
pixman_region32_t *output_damage);
/** See weston_renderer_resize_output()
*
* \return True for success, false for leaving the output in a mess.
*/
bool (*resize_output)(struct weston_output *output,
const struct weston_size *fb_size,
const struct weston_geometry *area);
void (*flush_damage)(struct weston_surface *surface,
struct weston_buffer *buffer);
void (*attach)(struct weston_surface *es, struct weston_buffer *buffer);
......@@ -74,6 +84,28 @@ struct weston_renderer {
struct weston_buffer *buffer);
};
void
weston_renderer_resize_output(struct weston_output *output,
const struct weston_size *fb_size,
const struct weston_geometry *area);
static inline void
check_compositing_area(const struct weston_size *fb_size,
const struct weston_geometry *area)
{
assert(fb_size);
assert(fb_size->width > 0);
assert(fb_size->height > 0);
assert(area);
assert(area->x >= 0);
assert(area->width > 0);
assert(area->x <= fb_size->width - area->width);
assert(area->y >= 0);
assert(area->height > 0);
assert(area->y <= fb_size->height - area->height);
}
/* weston_buffer */
void
......
......@@ -51,6 +51,15 @@ noop_renderer_repaint_output(struct weston_output *output,
{
}
static bool
noop_renderer_resize_output(struct weston_output *output,
const struct weston_size *fb_size,
const struct weston_geometry *area)
{
check_compositing_area(fb_size, area);
return true;
}
static void
noop_renderer_flush_damage(struct weston_surface *surface,
struct weston_buffer *buffer)
......@@ -124,6 +133,7 @@ noop_renderer_init(struct weston_compositor *ec)
renderer->base.read_pixels = noop_renderer_read_pixels;
renderer->base.repaint_output = noop_renderer_repaint_output;
renderer->base.resize_output = noop_renderer_resize_output;
renderer->base.flush_damage = noop_renderer_flush_damage;
renderer->base.attach = noop_renderer_attach;
renderer->base.destroy = noop_renderer_destroy;
......
......@@ -37,13 +37,16 @@
#include "pixel-formats.h"
#include "shared/helpers.h"
#include "shared/signal.h"
#include "shared/weston-drm-fourcc.h"
#include <linux/input.h>
struct pixman_output_state {
pixman_image_t *shadow_image;
const struct pixel_format_info *shadow_format;
pixman_image_t *hw_buffer;
pixman_region32_t *hw_extra_damage;
struct weston_size fb_size;
};
struct pixman_surface_state {
......@@ -119,8 +122,8 @@ pixman_renderer_read_pixels(struct weston_output *output,
x, y, /* src_x, src_y */
0, 0, /* mask_x, mask_y */
0, 0, /* dest_x, dest_y */
pixman_image_get_width (po->hw_buffer), /* width */
pixman_image_get_height (po->hw_buffer) /* height */);
po->fb_size.width, /* width */
po->fb_size.height /* height */);
pixman_image_unref(out_buf);
......@@ -381,8 +384,8 @@ repaint_region(struct weston_view *ev, struct weston_output *output,
0, 0, /* src_x, src_y */
0, 0, /* mask_x, mask_y */
0, 0, /* dest_x, dest_y */
pixman_image_get_width (target_image), /* width */
pixman_image_get_height (target_image) /* height */);
po->fb_size.width, /* width */
po->fb_size.height /* height */);
pixman_image_set_clip_region32(target_image, NULL);
}
......@@ -571,8 +574,8 @@ copy_to_hw_buffer(struct weston_output *output, pixman_region32_t *region)
0, 0, /* src_x, src_y */
0, 0, /* mask_x, mask_y */
0, 0, /* dest_x, dest_y */
pixman_image_get_width (po->hw_buffer), /* width */
pixman_image_get_height (po->hw_buffer) /* height */);
po->fb_size.width, /* width */
po->fb_size.height /* height */);
pixman_image_set_clip_region32 (po->hw_buffer, NULL);
}
......@@ -843,6 +846,42 @@ pixman_renderer_surface_copy_content(struct weston_surface *surface,
return 0;
}
static bool
pixman_renderer_resize_output(struct weston_output *output,
const struct weston_size *fb_size,
const struct weston_geometry *area)
{
struct pixman_output_state *po = get_output_state(output);
check_compositing_area(fb_size, area);
/*
* Pixman-renderer does not implement output decorations blitting,
* wayland-backend does it on its own.
*/
assert(area->x == 0);
assert(area->y == 0);
assert(fb_size->width == area->width);
assert(fb_size->height == area->height);
pixman_renderer_output_set_buffer(output, NULL);
po->fb_size = *fb_size;
if (!po->shadow_format)
return true;
if (po->shadow_image)
pixman_image_unref(po->shadow_image);
po->shadow_image =
pixman_image_create_bits_no_clear(po->shadow_format->pixman_format,
fb_size->width, fb_size->height,
NULL, 0);
return !!po->shadow_image;
}
static void
debug_binding(struct weston_keyboard *keyboard, const struct timespec *time,
uint32_t key, void *data)
......@@ -879,6 +918,7 @@ pixman_renderer_init(struct weston_compositor *ec)
renderer->debug_color = NULL;
renderer->base.read_pixels = pixman_renderer_read_pixels;
renderer->base.repaint_output = pixman_renderer_repaint_output;
renderer->base.resize_output = pixman_renderer_resize_output;
renderer->base.flush_damage = pixman_renderer_flush_damage;
renderer->base.attach = pixman_renderer_attach;
renderer->base.destroy = pixman_renderer_destroy;
......@@ -929,6 +969,9 @@ pixman_renderer_output_set_buffer(struct weston_output *output,
output->compositor->read_format =
pixel_format_get_info_by_pixman(pixman_format);
pixman_image_ref(po->hw_buffer);
assert(po->fb_size.width == pixman_image_get_width(po->hw_buffer));
assert(po->fb_size.height == pixman_image_get_height(po->hw_buffer));
}
}
......@@ -946,29 +989,28 @@ pixman_renderer_output_create(struct weston_output *output,
const struct pixman_renderer_output_options *options)
{
struct pixman_output_state *po;
int w, h;
struct weston_geometry area = {
.x = 0,
.y = 0,
.width = options->fb_size.width,
.height = options->fb_size.height
};
po = zalloc(sizeof *po);
if (po == NULL)
return -1;
if (options->use_shadow) {
/* set shadow image transformation */
w = output->current_mode->width;
h = output->current_mode->height;
output->renderer_state = po;
po->shadow_image =
pixman_image_create_bits_no_clear(PIXMAN_x8r8g8b8,
w, h, NULL, 0);
if (options->use_shadow)
po->shadow_format = pixel_format_get_info(DRM_FORMAT_XRGB8888);
if (!po->shadow_image) {
free(po);
return -1;
}
if (!pixman_renderer_resize_output(output, &options->fb_size, &area)) {
output->renderer_state = NULL;
free(po);
return -1;
}
output->renderer_state = po;
return 0;
}
......
......@@ -35,6 +35,8 @@ pixman_renderer_init(struct weston_compositor *ec);
struct pixman_renderer_output_options {
/** Composite into a shadow buffer, copying to the hardware buffer */
bool use_shadow;
/** Initial framebuffer size */
struct weston_size fb_size;
};
int
......
......@@ -89,6 +89,9 @@ struct gl_fbo_texture {
};
struct gl_output_state {
struct weston_size fb_size; /**< in pixels, including borders */
struct weston_geometry area; /**< composited area in pixels inside fb */
EGLSurface egl_surface;
pixman_region32_t buffer_damage[BUFFER_DAMAGE_COUNT];
int buffer_damage_index;
......@@ -104,6 +107,7 @@ struct gl_output_state {
/* struct timeline_render_point::link */
struct wl_list timeline_render_point_list;
const struct pixel_format_info *shadow_format;
struct gl_fbo_texture shadow;
};
......@@ -1621,12 +1625,8 @@ gl_renderer_repaint_output(struct weston_output *output,
/* If using shadow, redirect all drawing to it first. */
if (shadow_exists(go)) {
/* XXX: Shadow code does not support resizing. */
assert(output->current_mode->width == go->shadow.width);
assert(output->current_mode->height == go->shadow.height);
glBindFramebuffer(GL_FRAMEBUFFER, go->shadow.fbo);
glViewport(0, 0, go->shadow.width, go->shadow.height);
glViewport(0, 0, go->area.width, go->area.height);
} else {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(go->borders[GL_RENDERER_BORDER_LEFT].width,
......@@ -3260,6 +3260,32 @@ gl_renderer_output_set_border(struct weston_output *output,
go->border_status |= 1 << side;
}
static bool
gl_renderer_resize_output(struct weston_output *output,
const struct weston_size *fb_size,
const struct weston_geometry *area)
{
struct gl_output_state *go = get_output_state(output);
const struct pixel_format_info *shfmt = go->shadow_format;
bool ret;
check_compositing_area(fb_size, area);
go->fb_size = *fb_size;
go->area = *area;
if (!shfmt)
return true;
if (shadow_exists(go))
gl_fbo_texture_fini(&go->shadow);
ret = gl_fbo_texture_init(&go->shadow, area->width, area->height,
shfmt->gl_format, GL_RGBA, shfmt->gl_type);
return ret;
}
static int
gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface);
......@@ -3295,12 +3321,13 @@ gl_renderer_create_window_surface(struct gl_renderer *gr,
static int
gl_renderer_output_create(struct weston_output *output,
EGLSurface surface)
EGLSurface surface,
const struct weston_size *fb_size,
const struct weston_geometry *area)
{
struct gl_output_state *go;
struct gl_renderer *gr = get_renderer(output->compositor);
const struct weston_testsuite_quirks *quirks;
bool ret;
int i;
quirks = &output->compositor->test_data.test_quirks;
......@@ -3324,23 +3351,25 @@ gl_renderer_output_create(struct weston_output *output,
quirks->gl_force_full_redraw_of_shadow_fb) {
assert(gr->gl_supports_color_transforms);
ret = gl_fbo_texture_init(&go->shadow,
output->current_mode->width,
output->current_mode->height,
GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT);
if (ret) {
weston_log("Output %s uses 16F shadow.\n",
output->name);
} else {
weston_log("Output %s failed to create 16F shadow.\n",
output->name);
free(go);
return -1;
}
go->shadow_format =
pixel_format_get_info(DRM_FORMAT_ABGR16161616F);
}
output->renderer_state = go;
if (!gl_renderer_resize_output(output, fb_size, area)) {
weston_log("Output %s failed to create 16F shadow.\n",
output->name);
output->renderer_state = NULL;
free(go);
return -1;
}
if (shadow_exists(go)) {
weston_log("Output %s uses 16F shadow.\n",
output->name);
}
return 0;
}
......@@ -3363,7 +3392,8 @@ gl_renderer_output_window_create(struct weston_output *output,
return -1;
}
ret = gl_renderer_output_create(output, egl_surface);
ret = gl_renderer_output_create(output, egl_surface,
&options->fb_size, &options->area);
if (ret < 0)
weston_platform_destroy_egl_surface(gr->egl_display, egl_surface);
......@@ -3381,8 +3411,8 @@ gl_renderer_output_pbuffer_create(struct weston_output *output,
EGLint value = 0;
int ret;
EGLint pbuffer_attribs[] = {
EGL_WIDTH, options->width,
EGL_HEIGHT, options->height,
EGL_WIDTH, options->fb_size.width,
EGL_HEIGHT, options->fb_size.height,
EGL_NONE
};
......@@ -3413,7 +3443,8 @@ gl_renderer_output_pbuffer_create(struct weston_output *output,
" Continuing anyway.\n", value);
}
ret = gl_renderer_output_create(output, egl_surface);
ret = gl_renderer_output_create(output, egl_surface,
&options->fb_size, &options->area);
if (ret < 0) {
eglDestroySurface(gr->egl_display, egl_surface);
} else {
......@@ -3613,6 +3644,7 @@ gl_renderer_display_create(struct weston_compositor *ec,
gr->base.read_pixels = gl_renderer_read_pixels;
gr->base.repaint_output = gl_renderer_repaint_output;
gr->base.resize_output = gl_renderer_resize_output;
gr->base.flush_damage = gl_renderer_flush_damage;
gr->base.attach = gl_renderer_attach;
gr->base.destroy = gl_renderer_destroy;
......
......@@ -81,6 +81,10 @@ struct gl_renderer_output_options {
EGLNativeWindowType window_for_legacy;
/** Native window handle for \c eglCreatePlatformWindowSurface */
void *window_for_platform;
/** Size of the framebuffer in pixels, including borders */
struct weston_size fb_size;
/** Area inside the framebuffer in pixels for composited content */
struct weston_geometry area;
/** Array of DRM pixel formats acceptable for the window */
const uint32_t *drm_formats;
/** The \c drm_formats array length */
......@@ -88,10 +92,10 @@ struct gl_renderer_output_options {
};
struct gl_renderer_pbuffer_options {
/** Width of the rendering surface in pixels */
int width;
/** Height of the rendering surface in pixels */
int height;
/** Size of the framebuffer in pixels, including borders */
struct weston_size fb_size;
/** Area inside the framebuffer in pixels for composited content */
struct weston_geometry area;
/** Array of DRM pixel formats acceptable for the pbuffer */
const uint32_t *drm_formats;
/** The \c drm_formats array length */
......