aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlia Bozhinov <ammen99@gmail.com>2018-11-23 21:20:57 +0100
committerIlia Bozhinov <ammen99@gmail.com>2018-11-24 10:54:25 +0100
commitfb5691b6cc42cab42d0f15e8fbb25b2e1ff4ad0d (patch)
treeef46e76a5fa07a924ba51d1f71383d9ddec7330c
parentc70b8f64b7f1ea0a603517c7e6852ef3743a483a (diff)
output: add wlr_output_preferred_read_format()
The read format is dependent on the output, so we first need to make it current. This fixes a race condition in wlr-screencopy-v1 where a dmabuf client would cause EGL_NO_SURFACE to be bound at the time when screencopy needs to query for the preferred format, causing GL errors.
-rw-r--r--include/wlr/render/wlr_renderer.h5
-rw-r--r--include/wlr/types/wlr_output.h6
-rw-r--r--render/wlr_renderer.c9
-rw-r--r--types/wlr_output.c15
-rw-r--r--types/wlr_screencopy_v1.c2
5 files changed, 22 insertions, 15 deletions
diff --git a/include/wlr/render/wlr_renderer.h b/include/wlr/render/wlr_renderer.h
index 02b4a11e..9c031b7f 100644
--- a/include/wlr/render/wlr_renderer.h
+++ b/include/wlr/render/wlr_renderer.h
@@ -97,11 +97,6 @@ int wlr_renderer_get_dmabuf_formats(struct wlr_renderer *renderer,
int wlr_renderer_get_dmabuf_modifiers(struct wlr_renderer *renderer, int format,
uint64_t **modifiers);
/**
- * Get the preferred format for reading pixels.
- */
-bool wlr_renderer_preferred_read_format(struct wlr_renderer *renderer,
- enum wl_shm_format *fmt);
-/**
* Reads out of pixels of the currently bound surface into data. `stride` is in
* bytes.
*
diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h
index 557a3895..6d38152a 100644
--- a/include/wlr/types/wlr_output.h
+++ b/include/wlr/types/wlr_output.h
@@ -193,6 +193,12 @@ void wlr_output_effective_resolution(struct wlr_output *output,
*/
bool wlr_output_make_current(struct wlr_output *output, int *buffer_age);
/**
+ * Get the preferred format for reading pixels.
+ * This function might change the current rendering context.
+ */
+bool wlr_output_preferred_read_format(struct wlr_output *output,
+ enum wl_shm_format *fmt);
+/**
* Swaps the output buffers. If the time of the frame isn't known, set `when` to
* NULL. If the compositor doesn't support damage tracking, set `damage` to
* NULL.
diff --git a/render/wlr_renderer.c b/render/wlr_renderer.c
index ca1a337d..58731d7f 100644
--- a/render/wlr_renderer.c
+++ b/render/wlr_renderer.c
@@ -139,15 +139,6 @@ int wlr_renderer_get_dmabuf_modifiers(struct wlr_renderer *r, int format,
return r->impl->get_dmabuf_modifiers(r, format, modifiers);
}
-bool wlr_renderer_preferred_read_format(struct wlr_renderer *r,
- enum wl_shm_format *fmt) {
- if (!r->impl->preferred_read_format || !r->impl->read_pixels) {
- return false;
- }
- *fmt = r->impl->preferred_read_format(r);
- return true;
-}
-
bool wlr_renderer_read_pixels(struct wlr_renderer *r, enum wl_shm_format fmt,
uint32_t *flags, uint32_t stride, uint32_t width, uint32_t height,
uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y,
diff --git a/types/wlr_output.c b/types/wlr_output.c
index 71cb3eba..dc8e34b8 100644
--- a/types/wlr_output.c
+++ b/types/wlr_output.c
@@ -6,6 +6,7 @@
#include <time.h>
#include <wayland-server.h>
#include <wlr/interfaces/wlr_output.h>
+#include <wlr/render/interface.h>
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_box.h>
#include <wlr/types/wlr_matrix.h>
@@ -339,6 +340,20 @@ bool wlr_output_make_current(struct wlr_output *output, int *buffer_age) {
return output->impl->make_current(output, buffer_age);
}
+bool wlr_output_preferred_read_format(struct wlr_output *output,
+ enum wl_shm_format *fmt) {
+ if (!wlr_output_make_current(output, NULL)) {
+ return false;
+ }
+
+ struct wlr_renderer *renderer = wlr_backend_get_renderer(output->backend);
+ if (!renderer->impl->preferred_read_format || !renderer->impl->read_pixels) {
+ return false;
+ }
+ *fmt = renderer->impl->preferred_read_format(renderer);
+ return true;
+}
+
bool wlr_output_swap_buffers(struct wlr_output *output, struct timespec *when,
pixman_region32_t *damage) {
if (output->frame_pending) {
diff --git a/types/wlr_screencopy_v1.c b/types/wlr_screencopy_v1.c
index b186b89b..1d8550fe 100644
--- a/types/wlr_screencopy_v1.c
+++ b/types/wlr_screencopy_v1.c
@@ -219,7 +219,7 @@ static void capture_output(struct wl_client *client,
struct wlr_renderer *renderer = wlr_backend_get_renderer(output->backend);
assert(renderer);
- if (!wlr_renderer_preferred_read_format(renderer, &frame->format)) {
+ if (!wlr_output_preferred_read_format(frame->output, &frame->format)) {
wlr_log(WLR_ERROR,
"Failed to capture output: no read format supported by renderer");
goto error;