mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-04-21 06:46:46 -04:00
Merge branch 'single-pixel-optimize' into 'master'
Draft: wlr_renderer: Add single pixel optimization See merge request wlroots/wlroots!3650
This commit is contained in:
commit
e3cc1dda94
39 changed files with 1149 additions and 972 deletions
|
|
@ -16,6 +16,7 @@
|
||||||
#include <wlr/backend/interface.h>
|
#include <wlr/backend/interface.h>
|
||||||
#include <wlr/interfaces/wlr_output.h>
|
#include <wlr/interfaces/wlr_output.h>
|
||||||
#include <wlr/render/wlr_renderer.h>
|
#include <wlr/render/wlr_renderer.h>
|
||||||
|
#include <wlr/types/wlr_linux_dmabuf_v1.h>
|
||||||
#include <wlr/types/wlr_matrix.h>
|
#include <wlr/types/wlr_matrix.h>
|
||||||
#include <wlr/util/box.h>
|
#include <wlr/util/box.h>
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
|
|
@ -1491,7 +1492,7 @@ static void handle_page_flip(int fd, unsigned seq,
|
||||||
* interface.
|
* interface.
|
||||||
*/
|
*/
|
||||||
if (!drm->parent && plane->current_fb &&
|
if (!drm->parent && plane->current_fb &&
|
||||||
wlr_client_buffer_get(plane->current_fb->wlr_buf)) {
|
wlr_dmabuf_v1_buffer_is_buffer(plane->current_fb->wlr_buf)) {
|
||||||
present_flags |= WLR_OUTPUT_PRESENT_ZERO_COPY;
|
present_flags |= WLR_OUTPUT_PRESENT_ZERO_COPY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,14 +90,14 @@ struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_texture *tex = wlr_texture_from_buffer(renderer, buffer);
|
struct wlr_raster *raster = wlr_raster_create(buffer);
|
||||||
if (tex == NULL) {
|
if (!raster) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_buffer *dst = wlr_swapchain_acquire(surf->swapchain, NULL);
|
struct wlr_buffer *dst = wlr_swapchain_acquire(surf->swapchain, NULL);
|
||||||
if (!dst) {
|
if (!dst) {
|
||||||
wlr_texture_destroy(tex);
|
wlr_raster_unlock(raster);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,16 +107,15 @@ struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf,
|
||||||
|
|
||||||
if (!wlr_renderer_begin_with_buffer(renderer, dst)) {
|
if (!wlr_renderer_begin_with_buffer(renderer, dst)) {
|
||||||
wlr_buffer_unlock(dst);
|
wlr_buffer_unlock(dst);
|
||||||
wlr_texture_destroy(tex);
|
wlr_raster_unlock(raster);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_renderer_clear(renderer, (float[]){ 0.0, 0.0, 0.0, 0.0 });
|
wlr_renderer_clear(renderer, (float[]){ 0.0, 0.0, 0.0, 0.0 });
|
||||||
wlr_render_texture_with_matrix(renderer, tex, mat, 1.0f);
|
wlr_render_raster_with_matrix(renderer, raster, mat, 1.0f);
|
||||||
|
|
||||||
wlr_renderer_end(renderer);
|
wlr_renderer_end(renderer);
|
||||||
|
wlr_raster_unlock(raster);
|
||||||
wlr_texture_destroy(tex);
|
|
||||||
|
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,8 @@ static void render_surface(struct wlr_surface *surface,
|
||||||
struct render_data *rdata = data;
|
struct render_data *rdata = data;
|
||||||
struct wlr_output *output = rdata->output;
|
struct wlr_output *output = rdata->output;
|
||||||
|
|
||||||
struct wlr_texture *texture = wlr_surface_get_texture(surface);
|
struct wlr_raster *raster = wlr_raster_create(surface->current.buffer);
|
||||||
if (texture == NULL) {
|
if (raster == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,9 +74,11 @@ static void render_surface(struct wlr_surface *surface,
|
||||||
wlr_matrix_project_box(matrix, &box, transform, 0,
|
wlr_matrix_project_box(matrix, &box, transform, 0,
|
||||||
output->transform_matrix);
|
output->transform_matrix);
|
||||||
|
|
||||||
wlr_render_texture_with_matrix(rdata->renderer, texture, matrix, 1);
|
wlr_render_raster_with_matrix(rdata->renderer, raster, matrix, 1);
|
||||||
|
|
||||||
wlr_surface_send_frame_done(surface, rdata->when);
|
wlr_surface_send_frame_done(surface, rdata->when);
|
||||||
|
|
||||||
|
wlr_raster_unlock(raster);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void output_handle_frame(struct wl_listener *listener, void *data) {
|
static void output_handle_frame(struct wl_listener *listener, void *data) {
|
||||||
|
|
@ -211,7 +213,7 @@ int main(int argc, char *argv[]) {
|
||||||
server.allocator = wlr_allocator_autocreate(server.backend,
|
server.allocator = wlr_allocator_autocreate(server.backend,
|
||||||
server.renderer);
|
server.renderer);
|
||||||
|
|
||||||
wlr_compositor_create(server.wl_display, server.renderer);
|
wlr_compositor_create(server.wl_display);
|
||||||
|
|
||||||
server.output_layout = wlr_output_layout_create();
|
server.output_layout = wlr_output_layout_create();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ struct sample_state {
|
||||||
struct wl_listener new_input;
|
struct wl_listener new_input;
|
||||||
struct wlr_renderer *renderer;
|
struct wlr_renderer *renderer;
|
||||||
struct wlr_allocator *allocator;
|
struct wlr_allocator *allocator;
|
||||||
struct wlr_texture *cat_texture;
|
struct wlr_raster *cat_raster;
|
||||||
struct wlr_output_layout *layout;
|
struct wlr_output_layout *layout;
|
||||||
float x_offs, y_offs;
|
float x_offs, y_offs;
|
||||||
float x_vel, y_vel;
|
float x_vel, y_vel;
|
||||||
|
|
@ -134,7 +134,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
|
||||||
wlr_output_layout_output_coords(sample->layout, output->output,
|
wlr_output_layout_output_coords(sample->layout, output->output,
|
||||||
&local_x, &local_y);
|
&local_x, &local_y);
|
||||||
|
|
||||||
wlr_render_texture(sample->renderer, sample->cat_texture,
|
wlr_render_raster(sample->renderer, sample->cat_raster,
|
||||||
wlr_output->transform_matrix, local_x, local_y, 1.0f);
|
wlr_output->transform_matrix, local_x, local_y, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -279,9 +279,8 @@ int main(int argc, char *argv[]) {
|
||||||
state.new_input.notify = new_input_notify;
|
state.new_input.notify = new_input_notify;
|
||||||
|
|
||||||
state.renderer = wlr_renderer_autocreate(wlr);
|
state.renderer = wlr_renderer_autocreate(wlr);
|
||||||
state.cat_texture = wlr_texture_from_pixels(state.renderer,
|
state.cat_raster = wlr_raster_from_pixels(DRM_FORMAT_ABGR8888,
|
||||||
DRM_FORMAT_ABGR8888, cat_tex.width * 4, cat_tex.width, cat_tex.height,
|
cat_tex.width * 4, cat_tex.width, cat_tex.height, cat_tex.pixel_data);
|
||||||
cat_tex.pixel_data);
|
|
||||||
|
|
||||||
state.allocator = wlr_allocator_autocreate(wlr, state.renderer);
|
state.allocator = wlr_allocator_autocreate(wlr, state.renderer);
|
||||||
|
|
||||||
|
|
@ -292,7 +291,7 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
wl_display_run(display);
|
wl_display_run(display);
|
||||||
|
|
||||||
wlr_texture_destroy(state.cat_texture);
|
wlr_raster_unlock(state.cat_raster);
|
||||||
|
|
||||||
wl_display_destroy(state.display);
|
wl_display_destroy(state.display);
|
||||||
wlr_output_layout_destroy(state.layout);
|
wlr_output_layout_destroy(state.layout);
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ struct sample_state {
|
||||||
struct timespec last_frame;
|
struct timespec last_frame;
|
||||||
struct wlr_renderer *renderer;
|
struct wlr_renderer *renderer;
|
||||||
struct wlr_allocator *allocator;
|
struct wlr_allocator *allocator;
|
||||||
struct wlr_texture *cat_texture;
|
struct wlr_raster *cat_raster;
|
||||||
struct wl_list outputs;
|
struct wl_list outputs;
|
||||||
enum wl_output_transform transform;
|
enum wl_output_transform transform;
|
||||||
};
|
};
|
||||||
|
|
@ -65,7 +65,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
|
||||||
|
|
||||||
for (int y = -128 + (int)sample_output->y_offs; y < height; y += 128) {
|
for (int y = -128 + (int)sample_output->y_offs; y < height; y += 128) {
|
||||||
for (int x = -128 + (int)sample_output->x_offs; x < width; x += 128) {
|
for (int x = -128 + (int)sample_output->x_offs; x < width; x += 128) {
|
||||||
wlr_render_texture(sample->renderer, sample->cat_texture,
|
wlr_render_raster(sample->renderer, sample->cat_raster,
|
||||||
wlr_output->transform_matrix, x, y, 1.0f);
|
wlr_output->transform_matrix, x, y, 1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -256,10 +256,9 @@ int main(int argc, char *argv[]) {
|
||||||
wlr_backend_destroy(wlr);
|
wlr_backend_destroy(wlr);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
state.cat_texture = wlr_texture_from_pixels(state.renderer,
|
state.cat_raster = wlr_raster_from_pixels(DRM_FORMAT_ABGR8888,
|
||||||
DRM_FORMAT_ABGR8888, cat_tex.width * 4, cat_tex.width, cat_tex.height,
|
cat_tex.width * 4, cat_tex.width, cat_tex.height, cat_tex.pixel_data);
|
||||||
cat_tex.pixel_data);
|
if (!state.cat_raster) {
|
||||||
if (!state.cat_texture) {
|
|
||||||
wlr_log(WLR_ERROR, "Could not start compositor, OOM");
|
wlr_log(WLR_ERROR, "Could not start compositor, OOM");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
@ -273,6 +272,6 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
wl_display_run(display);
|
wl_display_run(display);
|
||||||
|
|
||||||
wlr_texture_destroy(state.cat_texture);
|
wlr_raster_unlock(state.cat_raster);
|
||||||
wl_display_destroy(display);
|
wl_display_destroy(display);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ static void surface_handle_commit(struct wl_listener *listener, void *data) {
|
||||||
|
|
||||||
static void surface_handle_destroy(struct wl_listener *listener, void *data) {
|
static void surface_handle_destroy(struct wl_listener *listener, void *data) {
|
||||||
struct surface *surface = wl_container_of(listener, surface, destroy);
|
struct surface *surface = wl_container_of(listener, surface, destroy);
|
||||||
wlr_scene_node_destroy(&surface->scene_surface->buffer->node);
|
wlr_scene_node_destroy(&surface->scene_surface->raster->node);
|
||||||
wlr_scene_node_destroy(&surface->border->node);
|
wlr_scene_node_destroy(&surface->border->node);
|
||||||
wl_list_remove(&surface->destroy.link);
|
wl_list_remove(&surface->destroy.link);
|
||||||
wl_list_remove(&surface->link);
|
wl_list_remove(&surface->link);
|
||||||
|
|
@ -129,7 +129,7 @@ static void server_handle_new_surface(struct wl_listener *listener,
|
||||||
surface->scene_surface =
|
surface->scene_surface =
|
||||||
wlr_scene_surface_create(&server->scene->tree, wlr_surface);
|
wlr_scene_surface_create(&server->scene->tree, wlr_surface);
|
||||||
|
|
||||||
wlr_scene_node_set_position(&surface->scene_surface->buffer->node,
|
wlr_scene_node_set_position(&surface->scene_surface->raster->node,
|
||||||
pos + border_width, pos + border_width);
|
pos + border_width, pos + border_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,8 +166,7 @@ int main(int argc, char *argv[]) {
|
||||||
server.allocator = wlr_allocator_autocreate(server.backend,
|
server.allocator = wlr_allocator_autocreate(server.backend,
|
||||||
server.renderer);
|
server.renderer);
|
||||||
|
|
||||||
struct wlr_compositor *compositor =
|
struct wlr_compositor *compositor = wlr_compositor_create(server.display);
|
||||||
wlr_compositor_create(server.display, server.renderer);
|
|
||||||
|
|
||||||
wlr_xdg_shell_create(server.display, 2);
|
wlr_xdg_shell_create(server.display, 2);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ struct sample_state {
|
||||||
struct wl_display *display;
|
struct wl_display *display;
|
||||||
struct wlr_renderer *renderer;
|
struct wlr_renderer *renderer;
|
||||||
struct wlr_allocator *allocator;
|
struct wlr_allocator *allocator;
|
||||||
struct wlr_texture *cat_texture;
|
struct wlr_raster *cat_raster;
|
||||||
struct wl_list touch_points;
|
struct wl_list touch_points;
|
||||||
struct timespec last_frame;
|
struct timespec last_frame;
|
||||||
struct wl_listener new_output;
|
struct wl_listener new_output;
|
||||||
|
|
@ -81,9 +81,9 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
|
||||||
|
|
||||||
struct touch_point *p;
|
struct touch_point *p;
|
||||||
wl_list_for_each(p, &sample->touch_points, link) {
|
wl_list_for_each(p, &sample->touch_points, link) {
|
||||||
int x = (int)(p->x * width) - sample->cat_texture->width / 2;
|
int x = (int)(p->x * width) - sample->cat_raster->width / 2;
|
||||||
int y = (int)(p->y * height) - sample->cat_texture->height / 2;
|
int y = (int)(p->y * height) - sample->cat_raster->height / 2;
|
||||||
wlr_render_texture(sample->renderer, sample->cat_texture,
|
wlr_render_raster(sample->renderer, sample->cat_raster,
|
||||||
wlr_output->transform_matrix, x, y, 1.0f);
|
wlr_output->transform_matrix, x, y, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -264,10 +264,9 @@ int main(int argc, char *argv[]) {
|
||||||
wlr_log(WLR_ERROR, "Could not start compositor, OOM");
|
wlr_log(WLR_ERROR, "Could not start compositor, OOM");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
state.cat_texture = wlr_texture_from_pixels(state.renderer,
|
state.cat_raster = wlr_raster_from_pixels(DRM_FORMAT_ARGB8888,
|
||||||
DRM_FORMAT_ARGB8888, cat_tex.width * 4, cat_tex.width, cat_tex.height,
|
cat_tex.width * 4, cat_tex.width, cat_tex.height, cat_tex.pixel_data);
|
||||||
cat_tex.pixel_data);
|
if (!state.cat_raster) {
|
||||||
if (!state.cat_texture) {
|
|
||||||
wlr_log(WLR_ERROR, "Could not start compositor, OOM");
|
wlr_log(WLR_ERROR, "Could not start compositor, OOM");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
@ -281,6 +280,6 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
wl_display_run(display);
|
wl_display_run(display);
|
||||||
|
|
||||||
wlr_texture_destroy(state.cat_texture);
|
wlr_raster_unlock(state.cat_raster);
|
||||||
wl_display_destroy(display);
|
wl_display_destroy(display);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,6 @@ struct wlr_gles2_buffer {
|
||||||
|
|
||||||
struct wlr_gles2_texture {
|
struct wlr_gles2_texture {
|
||||||
struct wlr_texture wlr_texture;
|
struct wlr_texture wlr_texture;
|
||||||
struct wlr_gles2_renderer *renderer;
|
|
||||||
struct wl_list link; // wlr_gles2_renderer.textures
|
struct wl_list link; // wlr_gles2_renderer.textures
|
||||||
|
|
||||||
// Basically:
|
// Basically:
|
||||||
|
|
@ -123,13 +122,11 @@ const uint32_t *get_gles2_shm_formats(const struct wlr_gles2_renderer *renderer,
|
||||||
|
|
||||||
struct wlr_gles2_renderer *gles2_get_renderer(
|
struct wlr_gles2_renderer *gles2_get_renderer(
|
||||||
struct wlr_renderer *wlr_renderer);
|
struct wlr_renderer *wlr_renderer);
|
||||||
struct wlr_gles2_texture *gles2_get_texture(
|
struct wlr_gles2_texture *gles2_raster_upload(struct wlr_gles2_renderer *renderer,
|
||||||
struct wlr_texture *wlr_texture);
|
struct wlr_raster *wlr_raster);
|
||||||
|
|
||||||
struct wlr_texture *gles2_texture_from_wl_drm(struct wlr_renderer *wlr_renderer,
|
struct wlr_texture *gles2_texture_from_wl_drm(struct wlr_renderer *wlr_renderer,
|
||||||
struct wl_resource *data);
|
struct wl_resource *data);
|
||||||
struct wlr_texture *gles2_texture_from_buffer(struct wlr_renderer *wlr_renderer,
|
|
||||||
struct wlr_buffer *buffer);
|
|
||||||
void gles2_texture_destroy(struct wlr_gles2_texture *texture);
|
void gles2_texture_destroy(struct wlr_gles2_texture *texture);
|
||||||
|
|
||||||
void push_gles2_debug_(struct wlr_gles2_renderer *renderer,
|
void push_gles2_debug_(struct wlr_gles2_renderer *renderer,
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ struct wlr_pixman_buffer {
|
||||||
|
|
||||||
struct wlr_pixman_texture {
|
struct wlr_pixman_texture {
|
||||||
struct wlr_texture wlr_texture;
|
struct wlr_texture wlr_texture;
|
||||||
struct wlr_pixman_renderer *renderer;
|
|
||||||
struct wl_list link; // wlr_pixman_renderer.textures
|
struct wl_list link; // wlr_pixman_renderer.textures
|
||||||
|
|
||||||
pixman_image_t *image;
|
pixman_image_t *image;
|
||||||
|
|
|
||||||
|
|
@ -234,7 +234,6 @@ struct wlr_vk_renderer *vulkan_get_renderer(struct wlr_renderer *r);
|
||||||
// State (e.g. image texture) associated with a surface.
|
// State (e.g. image texture) associated with a surface.
|
||||||
struct wlr_vk_texture {
|
struct wlr_vk_texture {
|
||||||
struct wlr_texture wlr_texture;
|
struct wlr_texture wlr_texture;
|
||||||
struct wlr_vk_renderer *renderer;
|
|
||||||
uint32_t mem_count;
|
uint32_t mem_count;
|
||||||
VkDeviceMemory memories[WLR_DMABUF_MAX_PLANES];
|
VkDeviceMemory memories[WLR_DMABUF_MAX_PLANES];
|
||||||
VkImage image;
|
VkImage image;
|
||||||
|
|
@ -255,13 +254,12 @@ struct wlr_vk_texture {
|
||||||
struct wl_listener buffer_destroy;
|
struct wl_listener buffer_destroy;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_vk_texture *vulkan_get_texture(struct wlr_texture *wlr_texture);
|
struct wlr_vk_texture *vulkan_raster_upload(struct wlr_vk_renderer *renderer,
|
||||||
|
struct wlr_raster *wlr_raster);
|
||||||
VkImage vulkan_import_dmabuf(struct wlr_vk_renderer *renderer,
|
VkImage vulkan_import_dmabuf(struct wlr_vk_renderer *renderer,
|
||||||
const struct wlr_dmabuf_attributes *attribs,
|
const struct wlr_dmabuf_attributes *attribs,
|
||||||
VkDeviceMemory mems[static WLR_DMABUF_MAX_PLANES], uint32_t *n_mems,
|
VkDeviceMemory mems[static WLR_DMABUF_MAX_PLANES], uint32_t *n_mems,
|
||||||
bool for_render);
|
bool for_render);
|
||||||
struct wlr_texture *vulkan_texture_from_buffer(
|
|
||||||
struct wlr_renderer *wlr_renderer, struct wlr_buffer *buffer);
|
|
||||||
void vulkan_texture_destroy(struct wlr_vk_texture *texture);
|
void vulkan_texture_destroy(struct wlr_vk_texture *texture);
|
||||||
|
|
||||||
struct wlr_vk_descriptor_pool {
|
struct wlr_vk_descriptor_pool {
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,9 @@ struct wlr_shm_client_buffer {
|
||||||
struct wl_listener release;
|
struct wl_listener release;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool buffer_is_shm_client_buffer(struct wlr_buffer *buffer);
|
||||||
|
struct wlr_shm_client_buffer *shm_client_buffer_from_buffer(struct wlr_buffer *buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A read-only buffer that holds a data pointer.
|
* A read-only buffer that holds a data pointer.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
#include <wlr/render/wlr_renderer.h>
|
#include <wlr/render/wlr_renderer.h>
|
||||||
#include <wlr/render/wlr_texture.h>
|
#include <wlr/render/wlr_texture.h>
|
||||||
#include <wlr/types/wlr_output.h>
|
#include <wlr/types/wlr_output.h>
|
||||||
|
#include <wlr/types/wlr_raster.h>
|
||||||
#include <wlr/render/dmabuf.h>
|
#include <wlr/render/dmabuf.h>
|
||||||
|
|
||||||
struct wlr_box;
|
struct wlr_box;
|
||||||
|
|
@ -27,8 +28,10 @@ struct wlr_renderer_impl {
|
||||||
void (*end)(struct wlr_renderer *renderer);
|
void (*end)(struct wlr_renderer *renderer);
|
||||||
void (*clear)(struct wlr_renderer *renderer, const float color[static 4]);
|
void (*clear)(struct wlr_renderer *renderer, const float color[static 4]);
|
||||||
void (*scissor)(struct wlr_renderer *renderer, struct wlr_box *box);
|
void (*scissor)(struct wlr_renderer *renderer, struct wlr_box *box);
|
||||||
bool (*render_subtexture_with_matrix)(struct wlr_renderer *renderer,
|
bool (*raster_upload)(struct wlr_renderer *renderer,
|
||||||
struct wlr_texture *texture, const struct wlr_fbox *box,
|
struct wlr_raster *raster);
|
||||||
|
bool (*render_subraster_with_matrix)(struct wlr_renderer *renderer,
|
||||||
|
struct wlr_raster *raster, const struct wlr_fbox *box,
|
||||||
const float matrix[static 9], float alpha);
|
const float matrix[static 9], float alpha);
|
||||||
void (*render_quad_with_matrix)(struct wlr_renderer *renderer,
|
void (*render_quad_with_matrix)(struct wlr_renderer *renderer,
|
||||||
const float color[static 4], const float matrix[static 9]);
|
const float color[static 4], const float matrix[static 9]);
|
||||||
|
|
@ -46,22 +49,18 @@ struct wlr_renderer_impl {
|
||||||
void (*destroy)(struct wlr_renderer *renderer);
|
void (*destroy)(struct wlr_renderer *renderer);
|
||||||
int (*get_drm_fd)(struct wlr_renderer *renderer);
|
int (*get_drm_fd)(struct wlr_renderer *renderer);
|
||||||
uint32_t (*get_render_buffer_caps)(struct wlr_renderer *renderer);
|
uint32_t (*get_render_buffer_caps)(struct wlr_renderer *renderer);
|
||||||
struct wlr_texture *(*texture_from_buffer)(struct wlr_renderer *renderer,
|
|
||||||
struct wlr_buffer *buffer);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void wlr_renderer_init(struct wlr_renderer *renderer,
|
void wlr_renderer_init(struct wlr_renderer *renderer,
|
||||||
const struct wlr_renderer_impl *impl);
|
const struct wlr_renderer_impl *impl);
|
||||||
|
|
||||||
struct wlr_texture_impl {
|
struct wlr_texture_impl {
|
||||||
bool (*write_pixels)(struct wlr_texture *texture,
|
bool (*update_from_raster)(struct wlr_texture *texture,
|
||||||
uint32_t stride, uint32_t width, uint32_t height,
|
struct wlr_raster *raster, pixman_region32_t *damage);
|
||||||
uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y,
|
|
||||||
const void *data);
|
|
||||||
void (*destroy)(struct wlr_texture *texture);
|
void (*destroy)(struct wlr_texture *texture);
|
||||||
};
|
};
|
||||||
|
|
||||||
void wlr_texture_init(struct wlr_texture *texture,
|
void wlr_texture_init(struct wlr_texture *texture, struct wlr_renderer *rendener,
|
||||||
const struct wlr_texture_impl *impl, uint32_t width, uint32_t height);
|
const struct wlr_texture_impl *impl, uint32_t width, uint32_t height);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,5 @@ pixman_image_t *wlr_pixman_renderer_get_current_image(
|
||||||
|
|
||||||
bool wlr_renderer_is_pixman(struct wlr_renderer *wlr_renderer);
|
bool wlr_renderer_is_pixman(struct wlr_renderer *wlr_renderer);
|
||||||
bool wlr_texture_is_pixman(struct wlr_texture *texture);
|
bool wlr_texture_is_pixman(struct wlr_texture *texture);
|
||||||
pixman_image_t *wlr_pixman_texture_get_image(struct wlr_texture *wlr_texture);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -48,22 +48,30 @@ void wlr_renderer_clear(struct wlr_renderer *r, const float color[static 4]);
|
||||||
* box.
|
* box.
|
||||||
*/
|
*/
|
||||||
void wlr_renderer_scissor(struct wlr_renderer *r, struct wlr_box *box);
|
void wlr_renderer_scissor(struct wlr_renderer *r, struct wlr_box *box);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the requested texture.
|
* The renderer will attempt to upload the raster using an available compatible
|
||||||
|
* source found in the raster to the device that the renderer is running on.
|
||||||
|
* If the raster is already uploaded to said device, then this is a no-op.
|
||||||
*/
|
*/
|
||||||
bool wlr_render_texture(struct wlr_renderer *r, struct wlr_texture *texture,
|
bool wlr_renderer_raster_upload(struct wlr_renderer *r,
|
||||||
|
struct wlr_raster *raster);
|
||||||
|
/**
|
||||||
|
* Renders the requested raster.
|
||||||
|
*/
|
||||||
|
bool wlr_render_raster(struct wlr_renderer *r, struct wlr_raster *raster,
|
||||||
const float projection[static 9], int x, int y, float alpha);
|
const float projection[static 9], int x, int y, float alpha);
|
||||||
/**
|
/**
|
||||||
* Renders the requested texture using the provided matrix.
|
* Renders the requested raster using the provided matrix.
|
||||||
*/
|
*/
|
||||||
bool wlr_render_texture_with_matrix(struct wlr_renderer *r,
|
bool wlr_render_raster_with_matrix(struct wlr_renderer *r,
|
||||||
struct wlr_texture *texture, const float matrix[static 9], float alpha);
|
struct wlr_raster *raster, const float matrix[static 9], float alpha);
|
||||||
/**
|
/**
|
||||||
* Renders the requested texture using the provided matrix, after cropping it
|
* Renders the requested raster using the provided matrix, after cropping it
|
||||||
* to the provided rectangle.
|
* to the provided rectangle.
|
||||||
*/
|
*/
|
||||||
bool wlr_render_subtexture_with_matrix(struct wlr_renderer *r,
|
bool wlr_render_subraster_with_matrix(struct wlr_renderer *r,
|
||||||
struct wlr_texture *texture, const struct wlr_fbox *box,
|
struct wlr_raster *raster, const struct wlr_fbox *box,
|
||||||
const float matrix[static 9], float alpha);
|
const float matrix[static 9], float alpha);
|
||||||
/**
|
/**
|
||||||
* Renders a solid rectangle in the specified color.
|
* Renders a solid rectangle in the specified color.
|
||||||
|
|
|
||||||
|
|
@ -9,51 +9,40 @@
|
||||||
#ifndef WLR_RENDER_WLR_TEXTURE_H
|
#ifndef WLR_RENDER_WLR_TEXTURE_H
|
||||||
#define WLR_RENDER_WLR_TEXTURE_H
|
#define WLR_RENDER_WLR_TEXTURE_H
|
||||||
|
|
||||||
|
#include <pixman.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <wayland-server-core.h>
|
#include <wayland-server-core.h>
|
||||||
#include <wlr/render/dmabuf.h>
|
#include <wlr/types/wlr_raster.h>
|
||||||
|
|
||||||
struct wlr_buffer;
|
|
||||||
struct wlr_renderer;
|
struct wlr_renderer;
|
||||||
struct wlr_texture_impl;
|
struct wlr_texture_impl;
|
||||||
|
|
||||||
struct wlr_texture {
|
struct wlr_texture {
|
||||||
const struct wlr_texture_impl *impl;
|
const struct wlr_texture_impl *impl;
|
||||||
uint32_t width, height;
|
uint32_t width, height;
|
||||||
|
|
||||||
|
struct wlr_renderer *renderer;
|
||||||
|
|
||||||
|
struct wlr_raster *raster;
|
||||||
|
struct wl_list link;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new texture from raw pixel data. `stride` is in bytes. The returned
|
* Update a texture with a struct wlr_raster's contents.
|
||||||
* texture is mutable.
|
*
|
||||||
*/
|
* The update might be rejected (in case the texture is immutable, the raster
|
||||||
struct wlr_texture *wlr_texture_from_pixels(struct wlr_renderer *renderer,
|
* doesn't have a compatible source, unsupported type/format, etc), so callers
|
||||||
uint32_t fmt, uint32_t stride, uint32_t width, uint32_t height,
|
* must be prepared to fall back.
|
||||||
const void *data);
|
*
|
||||||
|
* The damage can be used by the renderer as an optimization: only the supplied
|
||||||
/**
|
* region needs to be updated.
|
||||||
* Create a new texture from a DMA-BUF. The returned texture is immutable.
|
|
||||||
*/
|
|
||||||
struct wlr_texture *wlr_texture_from_dmabuf(struct wlr_renderer *renderer,
|
|
||||||
struct wlr_dmabuf_attributes *attribs);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update a texture with raw pixels. The texture must be mutable, and the input
|
|
||||||
* data must have the same pixel format that the texture was created with.
|
|
||||||
*/
|
*/
|
||||||
bool wlr_texture_write_pixels(struct wlr_texture *texture,
|
bool wlr_texture_update_from_raster(struct wlr_texture *texture,
|
||||||
uint32_t stride, uint32_t width, uint32_t height,
|
struct wlr_raster *raster, pixman_region32_t *damage);
|
||||||
uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y,
|
|
||||||
const void *data);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroys the texture.
|
* Destroys the texture.
|
||||||
*/
|
*/
|
||||||
void wlr_texture_destroy(struct wlr_texture *texture);
|
void wlr_texture_destroy(struct wlr_texture *texture);
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new texture from a buffer.
|
|
||||||
*/
|
|
||||||
struct wlr_texture *wlr_texture_from_buffer(struct wlr_renderer *renderer,
|
|
||||||
struct wlr_buffer *buffer);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -132,53 +132,9 @@ bool wlr_buffer_begin_data_ptr_access(struct wlr_buffer *buffer, uint32_t flags,
|
||||||
void **data, uint32_t *format, size_t *stride);
|
void **data, uint32_t *format, size_t *stride);
|
||||||
void wlr_buffer_end_data_ptr_access(struct wlr_buffer *buffer);
|
void wlr_buffer_end_data_ptr_access(struct wlr_buffer *buffer);
|
||||||
|
|
||||||
/**
|
|
||||||
* A client buffer.
|
|
||||||
*/
|
|
||||||
struct wlr_client_buffer {
|
|
||||||
struct wlr_buffer base;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The buffer's texture, if any. A buffer will not have a texture if the
|
|
||||||
* client destroys the buffer before it has been released.
|
|
||||||
*/
|
|
||||||
struct wlr_texture *texture;
|
|
||||||
/**
|
|
||||||
* The buffer this client buffer was created from. NULL if destroyed.
|
|
||||||
*/
|
|
||||||
struct wlr_buffer *source;
|
|
||||||
|
|
||||||
// private state
|
|
||||||
|
|
||||||
struct wl_listener source_destroy;
|
|
||||||
|
|
||||||
// If the client buffer has been created from a wl_shm buffer
|
|
||||||
uint32_t shm_source_format;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a struct wlr_client_buffer from a given struct wlr_buffer by creating
|
|
||||||
* a texture from it, and copying its struct wl_resource.
|
|
||||||
*/
|
|
||||||
struct wlr_client_buffer *wlr_client_buffer_create(struct wlr_buffer *buffer,
|
|
||||||
struct wlr_renderer *renderer);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a client buffer from a generic buffer. If the buffer isn't a client
|
|
||||||
* buffer, returns NULL.
|
|
||||||
*/
|
|
||||||
struct wlr_client_buffer *wlr_client_buffer_get(struct wlr_buffer *buffer);
|
|
||||||
/**
|
/**
|
||||||
* Check if a resource is a wl_buffer resource.
|
* Check if a resource is a wl_buffer resource.
|
||||||
*/
|
*/
|
||||||
bool wlr_resource_is_buffer(struct wl_resource *resource);
|
bool wlr_resource_is_buffer(struct wl_resource *resource);
|
||||||
/**
|
|
||||||
* Try to update the buffer's content.
|
|
||||||
*
|
|
||||||
* Fails if there's more than one reference to the buffer or if the texture
|
|
||||||
* isn't mutable.
|
|
||||||
*/
|
|
||||||
bool wlr_client_buffer_apply_damage(struct wlr_client_buffer *client_buffer,
|
|
||||||
struct wlr_buffer *next, pixman_region32_t *damage);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -88,18 +88,17 @@ struct wlr_surface_output {
|
||||||
|
|
||||||
struct wlr_surface {
|
struct wlr_surface {
|
||||||
struct wl_resource *resource;
|
struct wl_resource *resource;
|
||||||
struct wlr_renderer *renderer;
|
|
||||||
/**
|
|
||||||
* The surface's buffer, if any. A surface has an attached buffer when it
|
|
||||||
* commits with a non-null buffer in its pending state. A surface will not
|
|
||||||
* have a buffer if it has never committed one, has committed a null buffer,
|
|
||||||
* or something went wrong with uploading the buffer.
|
|
||||||
*/
|
|
||||||
struct wlr_client_buffer *buffer;
|
|
||||||
/**
|
/**
|
||||||
* The buffer position, in surface-local units.
|
* The buffer position, in surface-local units.
|
||||||
*/
|
*/
|
||||||
int sx, sy;
|
int sx, sy;
|
||||||
|
/**
|
||||||
|
* The surface's raster, if any. A surface has an attached raster when it
|
||||||
|
* commits with a non-null buffer in its pending state. A surface will not
|
||||||
|
* have a raster if it has never committed one or has committed a null
|
||||||
|
* buffer.
|
||||||
|
*/
|
||||||
|
struct wlr_raster *raster;
|
||||||
/**
|
/**
|
||||||
* The last commit's buffer damage, in buffer-local coordinates. This
|
* The last commit's buffer damage, in buffer-local coordinates. This
|
||||||
* contains both the damage accumulated by the client via
|
* contains both the damage accumulated by the client via
|
||||||
|
|
@ -154,8 +153,6 @@ struct wlr_surface {
|
||||||
|
|
||||||
// private state
|
// private state
|
||||||
|
|
||||||
struct wl_listener renderer_destroy;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int32_t scale;
|
int32_t scale;
|
||||||
enum wl_output_transform transform;
|
enum wl_output_transform transform;
|
||||||
|
|
@ -164,13 +161,13 @@ struct wlr_surface {
|
||||||
} previous;
|
} previous;
|
||||||
|
|
||||||
bool opaque;
|
bool opaque;
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_renderer;
|
struct wlr_raster *old_raster;
|
||||||
|
struct wl_listener raster_destroy;
|
||||||
|
};
|
||||||
|
|
||||||
struct wlr_compositor {
|
struct wlr_compositor {
|
||||||
struct wl_global *global;
|
struct wl_global *global;
|
||||||
struct wlr_renderer *renderer;
|
|
||||||
|
|
||||||
struct wl_listener display_destroy;
|
struct wl_listener display_destroy;
|
||||||
|
|
||||||
|
|
@ -199,13 +196,6 @@ bool wlr_surface_set_role(struct wlr_surface *surface,
|
||||||
*/
|
*/
|
||||||
bool wlr_surface_has_buffer(struct wlr_surface *surface);
|
bool wlr_surface_has_buffer(struct wlr_surface *surface);
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the texture of the buffer currently attached to this surface. Returns
|
|
||||||
* NULL if no buffer is currently attached or if something went wrong with
|
|
||||||
* uploading the buffer.
|
|
||||||
*/
|
|
||||||
struct wlr_texture *wlr_surface_get_texture(struct wlr_surface *surface);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the root of the subsurface tree for this surface. Can return NULL if
|
* Get the root of the subsurface tree for this surface. Can return NULL if
|
||||||
* a surface in the tree has been destroyed.
|
* a surface in the tree has been destroyed.
|
||||||
|
|
@ -299,7 +289,6 @@ uint32_t wlr_surface_lock_pending(struct wlr_surface *surface);
|
||||||
*/
|
*/
|
||||||
void wlr_surface_unlock_cached(struct wlr_surface *surface, uint32_t seq);
|
void wlr_surface_unlock_cached(struct wlr_surface *surface, uint32_t seq);
|
||||||
|
|
||||||
struct wlr_compositor *wlr_compositor_create(struct wl_display *display,
|
struct wlr_compositor *wlr_compositor_create(struct wl_display *display);
|
||||||
struct wlr_renderer *renderer);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,12 @@ struct wlr_dmabuf_v1_buffer {
|
||||||
*/
|
*/
|
||||||
bool wlr_dmabuf_v1_resource_is_buffer(struct wl_resource *buffer_resource);
|
bool wlr_dmabuf_v1_resource_is_buffer(struct wl_resource *buffer_resource);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the given buffer was created via the linux-dmabuf
|
||||||
|
* buffer protocol, false otherwise
|
||||||
|
*/
|
||||||
|
bool wlr_dmabuf_v1_buffer_is_buffer(struct wlr_buffer *buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the struct wlr_dmabuf_buffer if the given resource was created
|
* Returns the struct wlr_dmabuf_buffer if the given resource was created
|
||||||
* via the linux-dmabuf buffer protocol.
|
* via the linux-dmabuf buffer protocol.
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ struct wlr_output_cursor {
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
|
|
||||||
// only when using a software cursor without a surface
|
// only when using a software cursor without a surface
|
||||||
struct wlr_texture *texture;
|
struct wlr_raster *raster;
|
||||||
|
|
||||||
// only when using a cursor surface
|
// only when using a cursor surface
|
||||||
struct wlr_surface *surface;
|
struct wlr_surface *surface;
|
||||||
|
|
@ -494,8 +494,8 @@ bool wlr_output_cursor_set_image(struct wlr_output_cursor *cursor,
|
||||||
int32_t hotspot_x, int32_t hotspot_y);
|
int32_t hotspot_x, int32_t hotspot_y);
|
||||||
void wlr_output_cursor_set_surface(struct wlr_output_cursor *cursor,
|
void wlr_output_cursor_set_surface(struct wlr_output_cursor *cursor,
|
||||||
struct wlr_surface *surface, int32_t hotspot_x, int32_t hotspot_y);
|
struct wlr_surface *surface, int32_t hotspot_x, int32_t hotspot_y);
|
||||||
bool wlr_output_cursor_set_buffer(struct wlr_output_cursor *cursor,
|
bool wlr_output_cursor_set_raster(struct wlr_output_cursor *cursor,
|
||||||
struct wlr_buffer *buffer, int32_t hotspot_x, int32_t hotspot_y);
|
struct wlr_raster *raster, int32_t hotspot_x, int32_t hotspot_y);
|
||||||
bool wlr_output_cursor_move(struct wlr_output_cursor *cursor,
|
bool wlr_output_cursor_move(struct wlr_output_cursor *cursor,
|
||||||
double x, double y);
|
double x, double y);
|
||||||
void wlr_output_cursor_destroy(struct wlr_output_cursor *cursor);
|
void wlr_output_cursor_destroy(struct wlr_output_cursor *cursor);
|
||||||
|
|
|
||||||
84
include/wlr/types/wlr_raster.h
Normal file
84
include/wlr/types/wlr_raster.h
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* This an unstable interface of wlroots. No guarantees are made regarding the
|
||||||
|
* future consistency of this API.
|
||||||
|
*/
|
||||||
|
#ifndef WLR_USE_UNSTABLE
|
||||||
|
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef WLR_TYPES_WLR_RASTER_H
|
||||||
|
#define WLR_TYPES_WLR_RASTER_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <wayland-server-core.h>
|
||||||
|
|
||||||
|
struct wlr_buffer;
|
||||||
|
struct wlr_texture;
|
||||||
|
|
||||||
|
struct wlr_raster {
|
||||||
|
// May be NULL
|
||||||
|
struct wlr_buffer *buffer;
|
||||||
|
uint32_t width, height;
|
||||||
|
|
||||||
|
struct wl_list sources; // struct wlr_texture
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct wl_signal destroy;
|
||||||
|
} events;
|
||||||
|
|
||||||
|
// private state
|
||||||
|
|
||||||
|
size_t n_locks;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new wlr_raster being backed by the given buffer.
|
||||||
|
* The creation funciton is referenced: once the creator is done with the raster,
|
||||||
|
* wlr_raster_unlock must be called.
|
||||||
|
*/
|
||||||
|
struct wlr_raster *wlr_raster_create(struct wlr_buffer *buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes and unlocks the buffer assolated with this raster. A raster must be
|
||||||
|
* created with a buffer so that there is a source of information for textures
|
||||||
|
* to be created from it, but once there is a texture, that can be used
|
||||||
|
* as the source of truth and so the buffer can be removed early for other
|
||||||
|
* purposes.
|
||||||
|
*/
|
||||||
|
void wlr_raster_remove_buffer(struct wlr_raster *raster);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lock the raster for use. As long as the raster has at least one lock, it
|
||||||
|
* will not be destroyed. The raster will be created with a reference count at 1
|
||||||
|
* meaning that whatever produced the raster, must call this funciton.
|
||||||
|
*/
|
||||||
|
struct wlr_raster *wlr_raster_lock(struct wlr_raster *raster);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unlock the raster. This must be called after wlr_raster_lock once the raster
|
||||||
|
* has been finished being used.
|
||||||
|
*/
|
||||||
|
void wlr_raster_unlock(struct wlr_raster *raster);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attaches a wlr_texture to the raster. Consumers of the raster can use the
|
||||||
|
* given texture for their rendering if needed. The pixel contents of the texture
|
||||||
|
* must be the same as the source buffer and other textures in the raster.
|
||||||
|
*/
|
||||||
|
void wlr_raster_attach(struct wlr_raster *raster, struct wlr_texture *texture);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detaches a wlr_texture from the raster. Once the texture is detached, ownership
|
||||||
|
* of the texture is given to the caller such that the caller may mutate the
|
||||||
|
* raster if it wishes.
|
||||||
|
*/
|
||||||
|
void wlr_raster_detach(struct wlr_raster *raster, struct wlr_texture *texture);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new raster from raw pixel data. `stride` is in bytes.
|
||||||
|
*/
|
||||||
|
struct wlr_raster *wlr_raster_from_pixels(uint32_t fmt, uint32_t stride,
|
||||||
|
uint32_t width, uint32_t height, const void *data);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#include <wayland-server-core.h>
|
#include <wayland-server-core.h>
|
||||||
#include <wlr/types/wlr_compositor.h>
|
#include <wlr/types/wlr_compositor.h>
|
||||||
#include <wlr/types/wlr_damage_ring.h>
|
#include <wlr/types/wlr_damage_ring.h>
|
||||||
|
#include <wlr/types/wlr_raster.h>
|
||||||
|
|
||||||
struct wlr_output;
|
struct wlr_output;
|
||||||
struct wlr_output_layout;
|
struct wlr_output_layout;
|
||||||
|
|
@ -30,21 +31,21 @@ struct wlr_xdg_surface;
|
||||||
struct wlr_layer_surface_v1;
|
struct wlr_layer_surface_v1;
|
||||||
|
|
||||||
struct wlr_scene_node;
|
struct wlr_scene_node;
|
||||||
struct wlr_scene_buffer;
|
struct wlr_scene_raster;
|
||||||
|
|
||||||
typedef void (*wlr_scene_node_iterator_func_t)(struct wlr_scene_node *node,
|
typedef void (*wlr_scene_node_iterator_func_t)(struct wlr_scene_node *node,
|
||||||
int sx, int sy, void *data);
|
int sx, int sy, void *data);
|
||||||
|
|
||||||
typedef bool (*wlr_scene_buffer_point_accepts_input_func_t)(
|
typedef bool (*wlr_scene_raster_point_accepts_input_func_t)(
|
||||||
struct wlr_scene_buffer *buffer, int sx, int sy);
|
struct wlr_scene_raster *raster, int sx, int sy);
|
||||||
|
|
||||||
typedef void (*wlr_scene_buffer_iterator_func_t)(
|
typedef void (*wlr_scene_raster_iterator_func_t)(
|
||||||
struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data);
|
struct wlr_scene_raster *raster, int sx, int sy, void *user_data);
|
||||||
|
|
||||||
enum wlr_scene_node_type {
|
enum wlr_scene_node_type {
|
||||||
WLR_SCENE_NODE_TREE,
|
WLR_SCENE_NODE_TREE,
|
||||||
WLR_SCENE_NODE_RECT,
|
WLR_SCENE_NODE_RECT,
|
||||||
WLR_SCENE_NODE_BUFFER,
|
WLR_SCENE_NODE_RASTER,
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A node is an object in the scene. */
|
/** A node is an object in the scene. */
|
||||||
|
|
@ -98,7 +99,7 @@ struct wlr_scene {
|
||||||
|
|
||||||
/** A scene-graph node displaying a single surface. */
|
/** A scene-graph node displaying a single surface. */
|
||||||
struct wlr_scene_surface {
|
struct wlr_scene_surface {
|
||||||
struct wlr_scene_buffer *buffer;
|
struct wlr_scene_raster *raster;
|
||||||
struct wlr_surface *surface;
|
struct wlr_surface *surface;
|
||||||
|
|
||||||
// private state
|
// private state
|
||||||
|
|
@ -120,12 +121,12 @@ struct wlr_scene_rect {
|
||||||
float color[4];
|
float color[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A scene-graph node displaying a buffer */
|
/** A scene-graph node displaying a raster */
|
||||||
struct wlr_scene_buffer {
|
struct wlr_scene_raster {
|
||||||
struct wlr_scene_node node;
|
struct wlr_scene_node node;
|
||||||
|
|
||||||
// May be NULL
|
// May be NULL
|
||||||
struct wlr_buffer *buffer;
|
struct wlr_raster *raster;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct wl_signal output_enter; // struct wlr_scene_output
|
struct wl_signal output_enter; // struct wlr_scene_output
|
||||||
|
|
@ -135,11 +136,11 @@ struct wlr_scene_buffer {
|
||||||
} events;
|
} events;
|
||||||
|
|
||||||
// May be NULL
|
// May be NULL
|
||||||
wlr_scene_buffer_point_accepts_input_func_t point_accepts_input;
|
wlr_scene_raster_point_accepts_input_func_t point_accepts_input;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The output that the largest area of this buffer is displayed on.
|
* The output that the largest area of this raster is displayed on.
|
||||||
* This may be NULL if the buffer is not currently displayed on any
|
* This may be NULL if the raster is not currently displayed on any
|
||||||
* outputs. This is the output that should be used for frame callbacks,
|
* outputs. This is the output that should be used for frame callbacks,
|
||||||
* presentation feedback, etc.
|
* presentation feedback, etc.
|
||||||
*/
|
*/
|
||||||
|
|
@ -148,7 +149,6 @@ struct wlr_scene_buffer {
|
||||||
// private state
|
// private state
|
||||||
|
|
||||||
uint64_t active_outputs;
|
uint64_t active_outputs;
|
||||||
struct wlr_texture *texture;
|
|
||||||
struct wlr_fbox src_box;
|
struct wlr_fbox src_box;
|
||||||
int dst_width, dst_height;
|
int dst_width, dst_height;
|
||||||
enum wl_output_transform transform;
|
enum wl_output_transform transform;
|
||||||
|
|
@ -240,12 +240,12 @@ void wlr_scene_node_reparent(struct wlr_scene_node *node,
|
||||||
*/
|
*/
|
||||||
bool wlr_scene_node_coords(struct wlr_scene_node *node, int *lx, int *ly);
|
bool wlr_scene_node_coords(struct wlr_scene_node *node, int *lx, int *ly);
|
||||||
/**
|
/**
|
||||||
* Call `iterator` on each buffer in the scene-graph, with the buffer's
|
* Call `iterator` on each raster in the scene-graph, with the raster's
|
||||||
* position in layout coordinates. The function is called from root to leaves
|
* position in layout coordinates. The function is called from root to leaves
|
||||||
* (in rendering order).
|
* (in rendering order).
|
||||||
*/
|
*/
|
||||||
void wlr_scene_node_for_each_buffer(struct wlr_scene_node *node,
|
void wlr_scene_node_for_each_raster(struct wlr_scene_node *node,
|
||||||
wlr_scene_buffer_iterator_func_t iterator, void *user_data);
|
wlr_scene_raster_iterator_func_t iterator, void *user_data);
|
||||||
/**
|
/**
|
||||||
* Find the topmost node in this scene-graph that contains the point at the
|
* Find the topmost node in this scene-graph that contains the point at the
|
||||||
* given layout-local coordinates. (For surface nodes, this means accepting
|
* given layout-local coordinates. (For surface nodes, this means accepting
|
||||||
|
|
@ -285,14 +285,14 @@ struct wlr_scene_tree *wlr_scene_tree_create(struct wlr_scene_tree *parent);
|
||||||
struct wlr_scene_surface *wlr_scene_surface_create(struct wlr_scene_tree *parent,
|
struct wlr_scene_surface *wlr_scene_surface_create(struct wlr_scene_tree *parent,
|
||||||
struct wlr_surface *surface);
|
struct wlr_surface *surface);
|
||||||
|
|
||||||
struct wlr_scene_buffer *wlr_scene_buffer_from_node(struct wlr_scene_node *node);
|
struct wlr_scene_raster *wlr_scene_raster_from_node(struct wlr_scene_node *node);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this buffer is backed by a surface, then the struct wlr_scene_surface is
|
* If this raster is backed by a surface, then the struct wlr_scene_surface is
|
||||||
* returned. If not, NULL will be returned.
|
* returned. If not, NULL will be returned.
|
||||||
*/
|
*/
|
||||||
struct wlr_scene_surface *wlr_scene_surface_from_buffer(
|
struct wlr_scene_surface *wlr_scene_surface_from_raster(
|
||||||
struct wlr_scene_buffer *scene_buffer);
|
struct wlr_scene_raster *scene_raster);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a node displaying a solid-colored rectangle to the scene-graph.
|
* Add a node displaying a solid-colored rectangle to the scene-graph.
|
||||||
|
|
@ -311,59 +311,59 @@ void wlr_scene_rect_set_size(struct wlr_scene_rect *rect, int width, int height)
|
||||||
void wlr_scene_rect_set_color(struct wlr_scene_rect *rect, const float color[static 4]);
|
void wlr_scene_rect_set_color(struct wlr_scene_rect *rect, const float color[static 4]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a node displaying a buffer to the scene-graph.
|
* Add a node displaying a raster to the scene-graph.
|
||||||
*
|
*
|
||||||
* If the buffer is NULL, this node will not be displayed.
|
* If the raster is NULL, this node will not be displayed.
|
||||||
*/
|
*/
|
||||||
struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent,
|
struct wlr_scene_raster *wlr_scene_raster_create(struct wlr_scene_tree *parent,
|
||||||
struct wlr_buffer *buffer);
|
struct wlr_raster *raster);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the buffer's backing buffer.
|
* Sets the raster's backing raster.
|
||||||
*
|
*
|
||||||
* If the buffer is NULL, the buffer node will not be displayed.
|
* If the raster is NULL, the raster node will not be displayed.
|
||||||
*/
|
*/
|
||||||
void wlr_scene_buffer_set_buffer(struct wlr_scene_buffer *scene_buffer,
|
void wlr_scene_raster_set_raster(struct wlr_scene_raster *scene_raster,
|
||||||
struct wlr_buffer *buffer);
|
struct wlr_raster *raster);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the buffer's backing buffer with a custom damage region.
|
* Sets the raster's backing raster with a custom damage region.
|
||||||
*
|
*
|
||||||
* The damage region is in buffer-local coordinates. If the region is NULL,
|
* The damage region is in raster-local coordinates. If the region is NULL,
|
||||||
* the whole buffer node will be damaged.
|
* the whole raster node will be damaged.
|
||||||
*/
|
*/
|
||||||
void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buffer,
|
void wlr_scene_raster_set_raster_with_damage(struct wlr_scene_raster *scene_raster,
|
||||||
struct wlr_buffer *buffer, pixman_region32_t *region);
|
struct wlr_raster *raster, pixman_region32_t *region);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the source rectangle describing the region of the buffer which will be
|
* Set the source rectangle describing the region of the raster which will be
|
||||||
* sampled to render this node. This allows cropping the buffer.
|
* sampled to render this node. This allows cropping the raster.
|
||||||
*
|
*
|
||||||
* If NULL, the whole buffer is sampled. By default, the source box is NULL.
|
* If NULL, the whole raster is sampled. By default, the source box is NULL.
|
||||||
*/
|
*/
|
||||||
void wlr_scene_buffer_set_source_box(struct wlr_scene_buffer *scene_buffer,
|
void wlr_scene_raster_set_source_box(struct wlr_scene_raster *scene_raster,
|
||||||
const struct wlr_fbox *box);
|
const struct wlr_fbox *box);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the destination size describing the region of the scene-graph the buffer
|
* Set the destination size describing the region of the scene-graph the raster
|
||||||
* will be painted onto. This allows scaling the buffer.
|
* will be painted onto. This allows scaling the raster.
|
||||||
*
|
*
|
||||||
* If zero, the destination size will be the buffer size. By default, the
|
* If zero, the destination size will be the raster size. By default, the
|
||||||
* destination size is zero.
|
* destination size is zero.
|
||||||
*/
|
*/
|
||||||
void wlr_scene_buffer_set_dest_size(struct wlr_scene_buffer *scene_buffer,
|
void wlr_scene_raster_set_dest_size(struct wlr_scene_raster *scene_raster,
|
||||||
int width, int height);
|
int width, int height);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a transform which will be applied to the buffer.
|
* Set a transform which will be applied to the raster.
|
||||||
*/
|
*/
|
||||||
void wlr_scene_buffer_set_transform(struct wlr_scene_buffer *scene_buffer,
|
void wlr_scene_raster_set_transform(struct wlr_scene_raster *scene_raster,
|
||||||
enum wl_output_transform transform);
|
enum wl_output_transform transform);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls the buffer's frame_done signal.
|
* Calls the raster's frame_done signal.
|
||||||
*/
|
*/
|
||||||
void wlr_scene_buffer_send_frame_done(struct wlr_scene_buffer *scene_buffer,
|
void wlr_scene_raster_send_frame_done(struct wlr_scene_raster *scene_raster,
|
||||||
struct timespec *now);
|
struct timespec *now);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -394,12 +394,12 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output);
|
||||||
void wlr_scene_output_send_frame_done(struct wlr_scene_output *scene_output,
|
void wlr_scene_output_send_frame_done(struct wlr_scene_output *scene_output,
|
||||||
struct timespec *now);
|
struct timespec *now);
|
||||||
/**
|
/**
|
||||||
* Call `iterator` on each buffer in the scene-graph visible on the output,
|
* Call `iterator` on each raster in the scene-graph visible on the output,
|
||||||
* with the buffer's position in layout coordinates. The function is called
|
* with the raster's position in layout coordinates. The function is called
|
||||||
* from root to leaves (in rendering order).
|
* from root to leaves (in rendering order).
|
||||||
*/
|
*/
|
||||||
void wlr_scene_output_for_each_buffer(struct wlr_scene_output *scene_output,
|
void wlr_scene_output_for_each_raster(struct wlr_scene_output *scene_output,
|
||||||
wlr_scene_buffer_iterator_func_t iterator, void *user_data);
|
wlr_scene_raster_iterator_func_t iterator, void *user_data);
|
||||||
/**
|
/**
|
||||||
* Get a scene-graph output from a struct wlr_output.
|
* Get a scene-graph output from a struct wlr_output.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -246,15 +246,17 @@ static void gles2_scissor(struct wlr_renderer *wlr_renderer,
|
||||||
pop_gles2_debug(renderer);
|
pop_gles2_debug(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gles2_render_subtexture_with_matrix(
|
static bool gles2_render_subraster_with_matrix(
|
||||||
struct wlr_renderer *wlr_renderer, struct wlr_texture *wlr_texture,
|
struct wlr_renderer *wlr_renderer, struct wlr_raster *wlr_raster,
|
||||||
const struct wlr_fbox *box, const float matrix[static 9],
|
const struct wlr_fbox *box, const float matrix[static 9],
|
||||||
float alpha) {
|
float alpha) {
|
||||||
struct wlr_gles2_renderer *renderer =
|
struct wlr_gles2_renderer *renderer =
|
||||||
gles2_get_renderer_in_context(wlr_renderer);
|
gles2_get_renderer_in_context(wlr_renderer);
|
||||||
struct wlr_gles2_texture *texture =
|
struct wlr_gles2_texture *texture =
|
||||||
gles2_get_texture(wlr_texture);
|
gles2_raster_upload(renderer, wlr_raster);
|
||||||
assert(texture->renderer == renderer);
|
if (!texture) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
struct wlr_gles2_tex_shader *shader = NULL;
|
struct wlr_gles2_tex_shader *shader = NULL;
|
||||||
|
|
||||||
|
|
@ -305,10 +307,10 @@ static bool gles2_render_subtexture_with_matrix(
|
||||||
glUniform1i(shader->tex, 0);
|
glUniform1i(shader->tex, 0);
|
||||||
glUniform1f(shader->alpha, alpha);
|
glUniform1f(shader->alpha, alpha);
|
||||||
|
|
||||||
const GLfloat x1 = box->x / wlr_texture->width;
|
const GLfloat x1 = box->x / wlr_raster->width;
|
||||||
const GLfloat y1 = box->y / wlr_texture->height;
|
const GLfloat y1 = box->y / wlr_raster->height;
|
||||||
const GLfloat x2 = (box->x + box->width) / wlr_texture->width;
|
const GLfloat x2 = (box->x + box->width) / wlr_raster->width;
|
||||||
const GLfloat y2 = (box->y + box->height) / wlr_texture->height;
|
const GLfloat y2 = (box->y + box->height) / wlr_raster->height;
|
||||||
const GLfloat texcoord[] = {
|
const GLfloat texcoord[] = {
|
||||||
x2, y1, // top right
|
x2, y1, // top right
|
||||||
x1, y1, // top left
|
x1, y1, // top left
|
||||||
|
|
@ -529,6 +531,13 @@ static void gles2_destroy(struct wlr_renderer *wlr_renderer) {
|
||||||
free(renderer);
|
free(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool _gles2_raster_upload(struct wlr_renderer *wlr_renderer,
|
||||||
|
struct wlr_raster *raster) {
|
||||||
|
struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer);
|
||||||
|
struct wlr_gles2_texture *texture = gles2_raster_upload(renderer, raster);
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct wlr_renderer_impl renderer_impl = {
|
static const struct wlr_renderer_impl renderer_impl = {
|
||||||
.destroy = gles2_destroy,
|
.destroy = gles2_destroy,
|
||||||
.bind_buffer = gles2_bind_buffer,
|
.bind_buffer = gles2_bind_buffer,
|
||||||
|
|
@ -536,7 +545,8 @@ static const struct wlr_renderer_impl renderer_impl = {
|
||||||
.end = gles2_end,
|
.end = gles2_end,
|
||||||
.clear = gles2_clear,
|
.clear = gles2_clear,
|
||||||
.scissor = gles2_scissor,
|
.scissor = gles2_scissor,
|
||||||
.render_subtexture_with_matrix = gles2_render_subtexture_with_matrix,
|
.raster_upload = _gles2_raster_upload,
|
||||||
|
.render_subraster_with_matrix = gles2_render_subraster_with_matrix,
|
||||||
.render_quad_with_matrix = gles2_render_quad_with_matrix,
|
.render_quad_with_matrix = gles2_render_quad_with_matrix,
|
||||||
.get_shm_texture_formats = gles2_get_shm_texture_formats,
|
.get_shm_texture_formats = gles2_get_shm_texture_formats,
|
||||||
.get_dmabuf_texture_formats = gles2_get_dmabuf_texture_formats,
|
.get_dmabuf_texture_formats = gles2_get_dmabuf_texture_formats,
|
||||||
|
|
@ -545,7 +555,6 @@ static const struct wlr_renderer_impl renderer_impl = {
|
||||||
.read_pixels = gles2_read_pixels,
|
.read_pixels = gles2_read_pixels,
|
||||||
.get_drm_fd = gles2_get_drm_fd,
|
.get_drm_fd = gles2_get_drm_fd,
|
||||||
.get_render_buffer_caps = gles2_get_render_buffer_caps,
|
.get_render_buffer_caps = gles2_get_render_buffer_caps,
|
||||||
.texture_from_buffer = gles2_texture_from_buffer,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void push_gles2_debug_(struct wlr_gles2_renderer *renderer,
|
void push_gles2_debug_(struct wlr_gles2_renderer *renderer,
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ bool wlr_texture_is_gles2(struct wlr_texture *wlr_texture) {
|
||||||
return wlr_texture->impl == &texture_impl;
|
return wlr_texture->impl == &texture_impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_gles2_texture *gles2_get_texture(
|
static struct wlr_gles2_texture *gles2_get_texture(
|
||||||
struct wlr_texture *wlr_texture) {
|
struct wlr_texture *wlr_texture) {
|
||||||
assert(wlr_texture_is_gles2(wlr_texture));
|
assert(wlr_texture_is_gles2(wlr_texture));
|
||||||
return (struct wlr_gles2_texture *)wlr_texture;
|
return (struct wlr_gles2_texture *)wlr_texture;
|
||||||
|
|
@ -44,14 +44,25 @@ static bool check_stride(const struct wlr_pixel_format_info *fmt,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gles2_texture_write_pixels(struct wlr_texture *wlr_texture,
|
static bool gles2_texture_update_from_raster(struct wlr_texture *wlr_texture,
|
||||||
uint32_t stride, uint32_t width, uint32_t height,
|
struct wlr_raster *raster, pixman_region32_t *damage) {
|
||||||
uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y,
|
|
||||||
const void *data) {
|
|
||||||
struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture);
|
struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture);
|
||||||
|
struct wlr_buffer *buffer = raster->buffer;
|
||||||
|
|
||||||
if (texture->target != GL_TEXTURE_2D || texture->image != EGL_NO_IMAGE_KHR) {
|
if (texture->target != GL_TEXTURE_2D || texture->image != EGL_NO_IMAGE_KHR) {
|
||||||
wlr_log(WLR_ERROR, "Cannot write pixels to immutable texture");
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *data;
|
||||||
|
uint32_t format;
|
||||||
|
size_t stride;
|
||||||
|
if (!wlr_buffer_begin_data_ptr_access(buffer,
|
||||||
|
WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format != texture->drm_format) {
|
||||||
|
wlr_buffer_end_data_ptr_access(buffer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,24 +74,37 @@ static bool gles2_texture_write_pixels(struct wlr_texture *wlr_texture,
|
||||||
drm_get_pixel_format_info(texture->drm_format);
|
drm_get_pixel_format_info(texture->drm_format);
|
||||||
assert(drm_fmt);
|
assert(drm_fmt);
|
||||||
|
|
||||||
if (!check_stride(drm_fmt, stride, width)) {
|
if (!check_stride(drm_fmt, stride, buffer->width)) {
|
||||||
|
wlr_buffer_end_data_ptr_access(buffer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct wlr_gles2_renderer *renderer =
|
||||||
|
gles2_get_renderer(texture->wlr_texture.renderer);
|
||||||
|
|
||||||
struct wlr_egl_context prev_ctx;
|
struct wlr_egl_context prev_ctx;
|
||||||
wlr_egl_save_context(&prev_ctx);
|
wlr_egl_save_context(&prev_ctx);
|
||||||
wlr_egl_make_current(texture->renderer->egl);
|
wlr_egl_make_current(renderer->egl);
|
||||||
|
|
||||||
push_gles2_debug(texture->renderer);
|
push_gles2_debug(renderer);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture->tex);
|
glBindTexture(GL_TEXTURE_2D, texture->tex);
|
||||||
|
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / (drm_fmt->bpp / 8));
|
int rects_len = 0;
|
||||||
glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, src_x);
|
pixman_box32_t *rects = pixman_region32_rectangles(damage, &rects_len);
|
||||||
glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, src_y);
|
|
||||||
|
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0, dst_x, dst_y, width, height,
|
for (int i = 0; i < rects_len; i++) {
|
||||||
fmt->gl_format, fmt->gl_type, data);
|
pixman_box32_t rect = rects[i];
|
||||||
|
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / (drm_fmt->bpp / 8));
|
||||||
|
glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, rect.x1);
|
||||||
|
glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, rect.y1);
|
||||||
|
|
||||||
|
int width = rect.x2 - rect.x1;
|
||||||
|
int height = rect.y2 - rect.y1;
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x1, rect.y1, width, height,
|
||||||
|
fmt->gl_format, fmt->gl_type, data);
|
||||||
|
}
|
||||||
|
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0);
|
||||||
glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
|
glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
|
||||||
|
|
@ -88,10 +112,12 @@ static bool gles2_texture_write_pixels(struct wlr_texture *wlr_texture,
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
pop_gles2_debug(texture->renderer);
|
pop_gles2_debug(renderer);
|
||||||
|
|
||||||
wlr_egl_restore_context(&prev_ctx);
|
wlr_egl_restore_context(&prev_ctx);
|
||||||
|
|
||||||
|
wlr_buffer_end_data_ptr_access(buffer);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -104,18 +130,21 @@ static bool gles2_texture_invalidate(struct wlr_gles2_texture *texture) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct wlr_gles2_renderer *renderer =
|
||||||
|
gles2_get_renderer(texture->wlr_texture.renderer);
|
||||||
|
|
||||||
struct wlr_egl_context prev_ctx;
|
struct wlr_egl_context prev_ctx;
|
||||||
wlr_egl_save_context(&prev_ctx);
|
wlr_egl_save_context(&prev_ctx);
|
||||||
wlr_egl_make_current(texture->renderer->egl);
|
wlr_egl_make_current(renderer->egl);
|
||||||
|
|
||||||
push_gles2_debug(texture->renderer);
|
push_gles2_debug(renderer);
|
||||||
|
|
||||||
glBindTexture(texture->target, texture->tex);
|
glBindTexture(texture->target, texture->tex);
|
||||||
texture->renderer->procs.glEGLImageTargetTexture2DOES(texture->target,
|
renderer->procs.glEGLImageTargetTexture2DOES(texture->target,
|
||||||
texture->image);
|
texture->image);
|
||||||
glBindTexture(texture->target, 0);
|
glBindTexture(texture->target, 0);
|
||||||
|
|
||||||
pop_gles2_debug(texture->renderer);
|
pop_gles2_debug(renderer);
|
||||||
|
|
||||||
wlr_egl_restore_context(&prev_ctx);
|
wlr_egl_restore_context(&prev_ctx);
|
||||||
|
|
||||||
|
|
@ -128,16 +157,20 @@ void gles2_texture_destroy(struct wlr_gles2_texture *texture) {
|
||||||
wlr_addon_finish(&texture->buffer_addon);
|
wlr_addon_finish(&texture->buffer_addon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct wlr_gles2_renderer *renderer =
|
||||||
|
gles2_get_renderer(texture->wlr_texture.renderer);
|
||||||
|
|
||||||
|
|
||||||
struct wlr_egl_context prev_ctx;
|
struct wlr_egl_context prev_ctx;
|
||||||
wlr_egl_save_context(&prev_ctx);
|
wlr_egl_save_context(&prev_ctx);
|
||||||
wlr_egl_make_current(texture->renderer->egl);
|
wlr_egl_make_current(renderer->egl);
|
||||||
|
|
||||||
push_gles2_debug(texture->renderer);
|
push_gles2_debug(renderer);
|
||||||
|
|
||||||
glDeleteTextures(1, &texture->tex);
|
glDeleteTextures(1, &texture->tex);
|
||||||
wlr_egl_destroy_image(texture->renderer->egl, texture->image);
|
wlr_egl_destroy_image(renderer->egl, texture->image);
|
||||||
|
|
||||||
pop_gles2_debug(texture->renderer);
|
pop_gles2_debug(renderer);
|
||||||
|
|
||||||
wlr_egl_restore_context(&prev_ctx);
|
wlr_egl_restore_context(&prev_ctx);
|
||||||
|
|
||||||
|
|
@ -156,7 +189,7 @@ static void gles2_texture_unref(struct wlr_texture *wlr_texture) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wlr_texture_impl texture_impl = {
|
static const struct wlr_texture_impl texture_impl = {
|
||||||
.write_pixels = gles2_texture_write_pixels,
|
.update_from_raster = gles2_texture_update_from_raster,
|
||||||
.destroy = gles2_texture_unref,
|
.destroy = gles2_texture_unref,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -168,18 +201,16 @@ static struct wlr_gles2_texture *gles2_texture_create(
|
||||||
wlr_log_errno(WLR_ERROR, "Allocation failed");
|
wlr_log_errno(WLR_ERROR, "Allocation failed");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
wlr_texture_init(&texture->wlr_texture, &texture_impl, width, height);
|
wlr_texture_init(&texture->wlr_texture, &renderer->wlr_renderer,
|
||||||
texture->renderer = renderer;
|
&texture_impl, width, height);
|
||||||
wl_list_insert(&renderer->textures, &texture->link);
|
wl_list_insert(&renderer->textures, &texture->link);
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_texture *gles2_texture_from_pixels(
|
static struct wlr_gles2_texture *gles2_texture_from_pixels(
|
||||||
struct wlr_renderer *wlr_renderer,
|
struct wlr_gles2_renderer *renderer,
|
||||||
uint32_t drm_format, uint32_t stride, uint32_t width,
|
uint32_t drm_format, uint32_t stride, uint32_t width,
|
||||||
uint32_t height, const void *data) {
|
uint32_t height, const void *data) {
|
||||||
struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer);
|
|
||||||
|
|
||||||
const struct wlr_gles2_pixel_format *fmt =
|
const struct wlr_gles2_pixel_format *fmt =
|
||||||
get_gles2_format_from_drm(drm_format);
|
get_gles2_format_from_drm(drm_format);
|
||||||
if (fmt == NULL) {
|
if (fmt == NULL) {
|
||||||
|
|
@ -231,7 +262,7 @@ static struct wlr_texture *gles2_texture_from_pixels(
|
||||||
|
|
||||||
wlr_egl_restore_context(&prev_ctx);
|
wlr_egl_restore_context(&prev_ctx);
|
||||||
|
|
||||||
return &texture->wlr_texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_texture *gles2_texture_from_dmabuf(
|
static struct wlr_texture *gles2_texture_from_dmabuf(
|
||||||
|
|
@ -303,7 +334,7 @@ static const struct wlr_addon_interface texture_addon_impl = {
|
||||||
.destroy = texture_handle_buffer_destroy,
|
.destroy = texture_handle_buffer_destroy,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct wlr_texture *gles2_texture_from_dmabuf_buffer(
|
static struct wlr_gles2_texture *gles2_texture_from_dmabuf_buffer(
|
||||||
struct wlr_gles2_renderer *renderer, struct wlr_buffer *buffer,
|
struct wlr_gles2_renderer *renderer, struct wlr_buffer *buffer,
|
||||||
struct wlr_dmabuf_attributes *dmabuf) {
|
struct wlr_dmabuf_attributes *dmabuf) {
|
||||||
struct wlr_addon *addon =
|
struct wlr_addon *addon =
|
||||||
|
|
@ -313,16 +344,16 @@ static struct wlr_texture *gles2_texture_from_dmabuf_buffer(
|
||||||
wl_container_of(addon, texture, buffer_addon);
|
wl_container_of(addon, texture, buffer_addon);
|
||||||
if (!gles2_texture_invalidate(texture)) {
|
if (!gles2_texture_invalidate(texture)) {
|
||||||
wlr_log(WLR_ERROR, "Failed to invalidate texture");
|
wlr_log(WLR_ERROR, "Failed to invalidate texture");
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
wlr_buffer_lock(texture->buffer);
|
wlr_buffer_lock(texture->buffer);
|
||||||
return &texture->wlr_texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_texture *wlr_texture =
|
struct wlr_texture *wlr_texture =
|
||||||
gles2_texture_from_dmabuf(&renderer->wlr_renderer, dmabuf);
|
gles2_texture_from_dmabuf(&renderer->wlr_renderer, dmabuf);
|
||||||
if (wlr_texture == NULL) {
|
if (wlr_texture == NULL) {
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture);
|
struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture);
|
||||||
|
|
@ -330,28 +361,50 @@ static struct wlr_texture *gles2_texture_from_dmabuf_buffer(
|
||||||
wlr_addon_init(&texture->buffer_addon, &buffer->addons,
|
wlr_addon_init(&texture->buffer_addon, &buffer->addons,
|
||||||
renderer, &texture_addon_impl);
|
renderer, &texture_addon_impl);
|
||||||
|
|
||||||
return &texture->wlr_texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_texture *gles2_texture_from_buffer(struct wlr_renderer *wlr_renderer,
|
struct wlr_gles2_texture *gles2_raster_upload(struct wlr_gles2_renderer *renderer,
|
||||||
struct wlr_buffer *buffer) {
|
struct wlr_raster *wlr_raster) {
|
||||||
struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer);
|
struct wlr_texture *raster_texture;
|
||||||
|
wl_list_for_each(raster_texture, &wlr_raster->sources, link) {
|
||||||
|
if (wlr_texture_is_gles2(raster_texture)) {
|
||||||
|
struct wlr_gles2_texture *gles2_tex =
|
||||||
|
(struct wlr_gles2_texture *)raster_texture;
|
||||||
|
if (gles2_tex->wlr_texture.renderer != &renderer->wlr_renderer) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return gles2_tex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_buffer *buffer = wlr_raster->buffer;
|
||||||
|
if (!wlr_raster->buffer) {
|
||||||
|
// we could possibly do a blit with another texture from another renderer,
|
||||||
|
// but this is unsupported currently.
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_gles2_texture *texture = NULL;
|
||||||
|
|
||||||
void *data;
|
void *data;
|
||||||
uint32_t format;
|
uint32_t format;
|
||||||
size_t stride;
|
size_t stride;
|
||||||
struct wlr_dmabuf_attributes dmabuf;
|
struct wlr_dmabuf_attributes dmabuf;
|
||||||
if (wlr_buffer_get_dmabuf(buffer, &dmabuf)) {
|
if (wlr_buffer_get_dmabuf(buffer, &dmabuf)) {
|
||||||
return gles2_texture_from_dmabuf_buffer(renderer, buffer, &dmabuf);
|
texture = gles2_texture_from_dmabuf_buffer(renderer, buffer, &dmabuf);
|
||||||
} else if (wlr_buffer_begin_data_ptr_access(buffer,
|
} else if (wlr_buffer_begin_data_ptr_access(buffer,
|
||||||
WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) {
|
WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) {
|
||||||
struct wlr_texture *tex = gles2_texture_from_pixels(wlr_renderer,
|
texture = gles2_texture_from_pixels(renderer,
|
||||||
format, stride, buffer->width, buffer->height, data);
|
format, stride, buffer->width, buffer->height, data);
|
||||||
wlr_buffer_end_data_ptr_access(buffer);
|
wlr_buffer_end_data_ptr_access(buffer);
|
||||||
return tex;
|
|
||||||
} else {
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (texture) {
|
||||||
|
wlr_raster_attach(wlr_raster, &texture->wlr_texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_gles2_texture_get_attribs(struct wlr_texture *wlr_texture,
|
void wlr_gles2_texture_get_attribs(struct wlr_texture *wlr_texture,
|
||||||
|
|
|
||||||
|
|
@ -40,14 +40,92 @@ bool wlr_texture_is_pixman(struct wlr_texture *texture) {
|
||||||
return texture->impl == &texture_impl;
|
return texture->impl == &texture_impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_pixman_texture *get_texture(
|
static struct wlr_pixman_texture *pixman_texture_create(
|
||||||
struct wlr_texture *wlr_texture) {
|
struct wlr_pixman_renderer *renderer, uint32_t drm_format,
|
||||||
assert(wlr_texture_is_pixman(wlr_texture));
|
uint32_t width, uint32_t height) {
|
||||||
return (struct wlr_pixman_texture *)wlr_texture;
|
struct wlr_pixman_texture *texture =
|
||||||
|
calloc(1, sizeof(struct wlr_pixman_texture));
|
||||||
|
if (texture == NULL) {
|
||||||
|
wlr_log_errno(WLR_ERROR, "Failed to allocate pixman texture");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_texture_init(&texture->wlr_texture, &renderer->wlr_renderer,
|
||||||
|
&texture_impl, width, height);
|
||||||
|
|
||||||
|
texture->format_info = drm_get_pixel_format_info(drm_format);
|
||||||
|
if (!texture->format_info) {
|
||||||
|
wlr_log(WLR_ERROR, "Unsupported drm format 0x%"PRIX32, drm_format);
|
||||||
|
free(texture);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
texture->format = get_pixman_format_from_drm(drm_format);
|
||||||
|
if (texture->format == 0) {
|
||||||
|
wlr_log(WLR_ERROR, "Unsupported pixman drm format 0x%"PRIX32,
|
||||||
|
drm_format);
|
||||||
|
free(texture);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_list_insert(&renderer->textures, &texture->link);
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct wlr_pixman_texture *raster_upload(
|
||||||
|
struct wlr_pixman_renderer *renderer, struct wlr_raster *wlr_raster) {
|
||||||
|
struct wlr_texture *raster_texture;
|
||||||
|
wl_list_for_each(raster_texture, &wlr_raster->sources, link) {
|
||||||
|
if (wlr_texture_is_pixman(raster_texture)) {
|
||||||
|
struct wlr_pixman_texture *pixman_tex =
|
||||||
|
(struct wlr_pixman_texture *)raster_texture;
|
||||||
|
if (pixman_tex->wlr_texture.renderer != &renderer->wlr_renderer) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return pixman_tex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_buffer *buffer = wlr_raster->buffer;
|
||||||
|
if (!buffer) {
|
||||||
|
// we could possibly do a blit with another texture from another renderer,
|
||||||
|
// but this is unsupported currently.
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *data = NULL;
|
||||||
|
uint32_t drm_format;
|
||||||
|
size_t stride;
|
||||||
|
if (!wlr_buffer_begin_data_ptr_access(buffer,
|
||||||
|
WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &drm_format, &stride)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
wlr_buffer_end_data_ptr_access(buffer);
|
||||||
|
|
||||||
|
struct wlr_pixman_texture *texture = pixman_texture_create(renderer,
|
||||||
|
drm_format, buffer->width, buffer->height);
|
||||||
|
if (texture == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
texture->image = pixman_image_create_bits_no_clear(texture->format,
|
||||||
|
buffer->width, buffer->height, data, stride);
|
||||||
|
if (!texture->image) {
|
||||||
|
wlr_log(WLR_ERROR, "Failed to create pixman image");
|
||||||
|
wl_list_remove(&texture->link);
|
||||||
|
free(texture);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
texture->buffer = wlr_buffer_lock(buffer);
|
||||||
|
|
||||||
|
wlr_raster_attach(wlr_raster, &texture->wlr_texture);
|
||||||
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void texture_destroy(struct wlr_texture *wlr_texture) {
|
static void texture_destroy(struct wlr_texture *wlr_texture) {
|
||||||
struct wlr_pixman_texture *texture = get_texture(wlr_texture);
|
struct wlr_pixman_texture *texture = (struct wlr_pixman_texture *)wlr_texture;
|
||||||
wl_list_remove(&texture->link);
|
wl_list_remove(&texture->link);
|
||||||
pixman_image_unref(texture->image);
|
pixman_image_unref(texture->image);
|
||||||
wlr_buffer_unlock(texture->buffer);
|
wlr_buffer_unlock(texture->buffer);
|
||||||
|
|
@ -215,13 +293,16 @@ static void matrix_to_pixman_transform(struct pixman_transform *transform,
|
||||||
pixman_transform_from_pixman_f_transform(transform, &ftr);
|
pixman_transform_from_pixman_f_transform(transform, &ftr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool pixman_render_subtexture_with_matrix(
|
static bool pixman_render_subraster_with_matrix(
|
||||||
struct wlr_renderer *wlr_renderer, struct wlr_texture *wlr_texture,
|
struct wlr_renderer *wlr_renderer, struct wlr_raster *wlr_raster,
|
||||||
const struct wlr_fbox *fbox, const float matrix[static 9],
|
const struct wlr_fbox *fbox, const float matrix[static 9],
|
||||||
float alpha) {
|
float alpha) {
|
||||||
struct wlr_pixman_renderer *renderer = get_renderer(wlr_renderer);
|
struct wlr_pixman_renderer *renderer = get_renderer(wlr_renderer);
|
||||||
struct wlr_pixman_texture *texture = get_texture(wlr_texture);
|
|
||||||
struct wlr_pixman_buffer *buffer = renderer->current_buffer;
|
struct wlr_pixman_buffer *buffer = renderer->current_buffer;
|
||||||
|
struct wlr_pixman_texture *texture = raster_upload(renderer, wlr_raster);
|
||||||
|
if (!texture){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (texture->buffer != NULL) {
|
if (texture->buffer != NULL) {
|
||||||
void *data;
|
void *data;
|
||||||
|
|
@ -334,72 +415,6 @@ static const struct wlr_drm_format_set *pixman_get_render_formats(
|
||||||
return &renderer->drm_formats;
|
return &renderer->drm_formats;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_pixman_texture *pixman_texture_create(
|
|
||||||
struct wlr_pixman_renderer *renderer, uint32_t drm_format,
|
|
||||||
uint32_t width, uint32_t height) {
|
|
||||||
struct wlr_pixman_texture *texture =
|
|
||||||
calloc(1, sizeof(struct wlr_pixman_texture));
|
|
||||||
if (texture == NULL) {
|
|
||||||
wlr_log_errno(WLR_ERROR, "Failed to allocate pixman texture");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
wlr_texture_init(&texture->wlr_texture, &texture_impl, width, height);
|
|
||||||
texture->renderer = renderer;
|
|
||||||
|
|
||||||
texture->format_info = drm_get_pixel_format_info(drm_format);
|
|
||||||
if (!texture->format_info) {
|
|
||||||
wlr_log(WLR_ERROR, "Unsupported drm format 0x%"PRIX32, drm_format);
|
|
||||||
free(texture);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
texture->format = get_pixman_format_from_drm(drm_format);
|
|
||||||
if (texture->format == 0) {
|
|
||||||
wlr_log(WLR_ERROR, "Unsupported pixman drm format 0x%"PRIX32,
|
|
||||||
drm_format);
|
|
||||||
free(texture);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_list_insert(&renderer->textures, &texture->link);
|
|
||||||
|
|
||||||
return texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct wlr_texture *pixman_texture_from_buffer(
|
|
||||||
struct wlr_renderer *wlr_renderer, struct wlr_buffer *buffer) {
|
|
||||||
struct wlr_pixman_renderer *renderer = get_renderer(wlr_renderer);
|
|
||||||
|
|
||||||
void *data = NULL;
|
|
||||||
uint32_t drm_format;
|
|
||||||
size_t stride;
|
|
||||||
if (!wlr_buffer_begin_data_ptr_access(buffer, WLR_BUFFER_DATA_PTR_ACCESS_READ,
|
|
||||||
&data, &drm_format, &stride)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
wlr_buffer_end_data_ptr_access(buffer);
|
|
||||||
|
|
||||||
struct wlr_pixman_texture *texture = pixman_texture_create(renderer,
|
|
||||||
drm_format, buffer->width, buffer->height);
|
|
||||||
if (texture == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
texture->image = pixman_image_create_bits_no_clear(texture->format,
|
|
||||||
buffer->width, buffer->height, data, stride);
|
|
||||||
if (!texture->image) {
|
|
||||||
wlr_log(WLR_ERROR, "Failed to create pixman image");
|
|
||||||
wl_list_remove(&texture->link);
|
|
||||||
free(texture);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
texture->buffer = wlr_buffer_lock(buffer);
|
|
||||||
|
|
||||||
return &texture->wlr_texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool pixman_bind_buffer(struct wlr_renderer *wlr_renderer,
|
static bool pixman_bind_buffer(struct wlr_renderer *wlr_renderer,
|
||||||
struct wlr_buffer *wlr_buffer) {
|
struct wlr_buffer *wlr_buffer) {
|
||||||
struct wlr_pixman_renderer *renderer = get_renderer(wlr_renderer);
|
struct wlr_pixman_renderer *renderer = get_renderer(wlr_renderer);
|
||||||
|
|
@ -488,16 +503,23 @@ static uint32_t pixman_get_render_buffer_caps(struct wlr_renderer *renderer) {
|
||||||
return WLR_BUFFER_CAP_DATA_PTR;
|
return WLR_BUFFER_CAP_DATA_PTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool pixman_raster_upload(struct wlr_renderer *wlr_renderer,
|
||||||
|
struct wlr_raster *raster) {
|
||||||
|
struct wlr_pixman_renderer *renderer = get_renderer(wlr_renderer);
|
||||||
|
struct wlr_pixman_texture *texture = raster_upload(renderer, raster);
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct wlr_renderer_impl renderer_impl = {
|
static const struct wlr_renderer_impl renderer_impl = {
|
||||||
.begin = pixman_begin,
|
.begin = pixman_begin,
|
||||||
.end = pixman_end,
|
.end = pixman_end,
|
||||||
.clear = pixman_clear,
|
.clear = pixman_clear,
|
||||||
.scissor = pixman_scissor,
|
.scissor = pixman_scissor,
|
||||||
.render_subtexture_with_matrix = pixman_render_subtexture_with_matrix,
|
.raster_upload = pixman_raster_upload,
|
||||||
|
.render_subraster_with_matrix = pixman_render_subraster_with_matrix,
|
||||||
.render_quad_with_matrix = pixman_render_quad_with_matrix,
|
.render_quad_with_matrix = pixman_render_quad_with_matrix,
|
||||||
.get_shm_texture_formats = pixman_get_shm_texture_formats,
|
.get_shm_texture_formats = pixman_get_shm_texture_formats,
|
||||||
.get_render_formats = pixman_get_render_formats,
|
.get_render_formats = pixman_get_render_formats,
|
||||||
.texture_from_buffer = pixman_texture_from_buffer,
|
|
||||||
.bind_buffer = pixman_bind_buffer,
|
.bind_buffer = pixman_bind_buffer,
|
||||||
.destroy = pixman_destroy,
|
.destroy = pixman_destroy,
|
||||||
.preferred_read_format = pixman_preferred_read_format,
|
.preferred_read_format = pixman_preferred_read_format,
|
||||||
|
|
@ -528,11 +550,6 @@ struct wlr_renderer *wlr_pixman_renderer_create(void) {
|
||||||
return &renderer->wlr_renderer;
|
return &renderer->wlr_renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
pixman_image_t *wlr_pixman_texture_get_image(struct wlr_texture *wlr_texture) {
|
|
||||||
struct wlr_pixman_texture *texture = get_texture(wlr_texture);
|
|
||||||
return texture->image;
|
|
||||||
}
|
|
||||||
|
|
||||||
pixman_image_t *wlr_pixman_renderer_get_current_image(
|
pixman_image_t *wlr_pixman_renderer_get_current_image(
|
||||||
struct wlr_renderer *wlr_renderer) {
|
struct wlr_renderer *wlr_renderer) {
|
||||||
struct wlr_pixman_renderer *renderer = get_renderer(wlr_renderer);
|
struct wlr_pixman_renderer *renderer = get_renderer(wlr_renderer);
|
||||||
|
|
|
||||||
|
|
@ -740,14 +740,17 @@ static void vulkan_end(struct wlr_renderer *wlr_renderer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool vulkan_render_subtexture_with_matrix(struct wlr_renderer *wlr_renderer,
|
static bool vulkan_render_subraster_with_matrix(struct wlr_renderer *wlr_renderer,
|
||||||
struct wlr_texture *wlr_texture, const struct wlr_fbox *box,
|
struct wlr_raster *wlr_raster, const struct wlr_fbox *box,
|
||||||
const float matrix[static 9], float alpha) {
|
const float matrix[static 9], float alpha) {
|
||||||
struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer);
|
struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer);
|
||||||
VkCommandBuffer cb = renderer->cb;
|
VkCommandBuffer cb = renderer->cb;
|
||||||
|
|
||||||
struct wlr_vk_texture *texture = vulkan_get_texture(wlr_texture);
|
struct wlr_vk_texture *texture = vulkan_raster_upload(renderer, wlr_raster);
|
||||||
assert(texture->renderer == renderer);
|
if (!texture) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (texture->dmabuf_imported && !texture->owned) {
|
if (texture->dmabuf_imported && !texture->owned) {
|
||||||
// Store this texture in the list of textures that need to be
|
// Store this texture in the list of textures that need to be
|
||||||
// acquired before rendering and released after rendering.
|
// acquired before rendering and released after rendering.
|
||||||
|
|
@ -776,10 +779,10 @@ static bool vulkan_render_subtexture_with_matrix(struct wlr_renderer *wlr_render
|
||||||
struct vert_pcr_data vert_pcr_data;
|
struct vert_pcr_data vert_pcr_data;
|
||||||
mat3_to_mat4(final_matrix, vert_pcr_data.mat4);
|
mat3_to_mat4(final_matrix, vert_pcr_data.mat4);
|
||||||
|
|
||||||
vert_pcr_data.uv_off[0] = box->x / wlr_texture->width;
|
vert_pcr_data.uv_off[0] = box->x / wlr_raster->width;
|
||||||
vert_pcr_data.uv_off[1] = box->y / wlr_texture->height;
|
vert_pcr_data.uv_off[1] = box->y / wlr_raster->height;
|
||||||
vert_pcr_data.uv_size[0] = box->width / wlr_texture->width;
|
vert_pcr_data.uv_size[0] = box->width / wlr_raster->width;
|
||||||
vert_pcr_data.uv_size[1] = box->height / wlr_texture->height;
|
vert_pcr_data.uv_size[1] = box->height / wlr_raster->height;
|
||||||
|
|
||||||
vkCmdPushConstants(cb, renderer->pipe_layout,
|
vkCmdPushConstants(cb, renderer->pipe_layout,
|
||||||
VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(vert_pcr_data), &vert_pcr_data);
|
VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(vert_pcr_data), &vert_pcr_data);
|
||||||
|
|
@ -976,13 +979,21 @@ static uint32_t vulkan_get_render_buffer_caps(struct wlr_renderer *wlr_renderer)
|
||||||
return WLR_BUFFER_CAP_DMABUF;
|
return WLR_BUFFER_CAP_DMABUF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool _vulkan_raster_upload(struct wlr_renderer *wlr_renderer,
|
||||||
|
struct wlr_raster *raster) {
|
||||||
|
struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer);
|
||||||
|
struct wlr_vk_texture *texture = vulkan_raster_upload(renderer, raster);
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct wlr_renderer_impl renderer_impl = {
|
static const struct wlr_renderer_impl renderer_impl = {
|
||||||
.bind_buffer = vulkan_bind_buffer,
|
.bind_buffer = vulkan_bind_buffer,
|
||||||
.begin = vulkan_begin,
|
.begin = vulkan_begin,
|
||||||
.end = vulkan_end,
|
.end = vulkan_end,
|
||||||
.clear = vulkan_clear,
|
.clear = vulkan_clear,
|
||||||
.scissor = vulkan_scissor,
|
.scissor = vulkan_scissor,
|
||||||
.render_subtexture_with_matrix = vulkan_render_subtexture_with_matrix,
|
.raster_upload = _vulkan_raster_upload,
|
||||||
|
.render_subraster_with_matrix = vulkan_render_subraster_with_matrix,
|
||||||
.render_quad_with_matrix = vulkan_render_quad_with_matrix,
|
.render_quad_with_matrix = vulkan_render_quad_with_matrix,
|
||||||
.get_shm_texture_formats = vulkan_get_shm_texture_formats,
|
.get_shm_texture_formats = vulkan_get_shm_texture_formats,
|
||||||
.get_dmabuf_texture_formats = vulkan_get_dmabuf_texture_formats,
|
.get_dmabuf_texture_formats = vulkan_get_dmabuf_texture_formats,
|
||||||
|
|
@ -992,7 +1003,6 @@ static const struct wlr_renderer_impl renderer_impl = {
|
||||||
.destroy = vulkan_destroy,
|
.destroy = vulkan_destroy,
|
||||||
.get_drm_fd = vulkan_get_drm_fd,
|
.get_drm_fd = vulkan_get_drm_fd,
|
||||||
.get_render_buffer_caps = vulkan_get_render_buffer_caps,
|
.get_render_buffer_caps = vulkan_get_render_buffer_caps,
|
||||||
.texture_from_buffer = vulkan_texture_from_buffer,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initializes the VkDescriptorSetLayout and VkPipelineLayout needed
|
// Initializes the VkDescriptorSetLayout and VkPipelineLayout needed
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ bool wlr_texture_is_vk(struct wlr_texture *wlr_texture) {
|
||||||
return wlr_texture->impl == &texture_impl;
|
return wlr_texture->impl == &texture_impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_vk_texture *vulkan_get_texture(struct wlr_texture *wlr_texture) {
|
static struct wlr_vk_texture *vulkan_get_texture(struct wlr_texture *wlr_texture) {
|
||||||
assert(wlr_texture_is_vk(wlr_texture));
|
assert(wlr_texture_is_vk(wlr_texture));
|
||||||
return (struct wlr_vk_texture *)wlr_texture;
|
return (struct wlr_vk_texture *)wlr_texture;
|
||||||
}
|
}
|
||||||
|
|
@ -42,8 +42,9 @@ static bool write_pixels(struct wlr_texture *wlr_texture,
|
||||||
VkAccessFlags src_access) {
|
VkAccessFlags src_access) {
|
||||||
VkResult res;
|
VkResult res;
|
||||||
struct wlr_vk_texture *texture = vulkan_get_texture(wlr_texture);
|
struct wlr_vk_texture *texture = vulkan_get_texture(wlr_texture);
|
||||||
struct wlr_vk_renderer *renderer = texture->renderer;
|
struct wlr_vk_renderer *renderer =
|
||||||
VkDevice dev = texture->renderer->dev->dev;
|
vulkan_get_renderer(wlr_texture->renderer);
|
||||||
|
VkDevice dev = renderer->dev->dev;
|
||||||
|
|
||||||
// make sure assumptions are met
|
// make sure assumptions are met
|
||||||
assert(src_x + width <= texture->wlr_texture.width);
|
assert(src_x + width <= texture->wlr_texture.width);
|
||||||
|
|
@ -136,27 +137,59 @@ static bool write_pixels(struct wlr_texture *wlr_texture,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool vulkan_texture_write_pixels(struct wlr_texture *wlr_texture,
|
static bool vulkan_texture_update_from_raster(struct wlr_texture *wlr_texture,
|
||||||
uint32_t stride, uint32_t width, uint32_t height, uint32_t src_x,
|
struct wlr_raster *raster, pixman_region32_t *damage) {
|
||||||
uint32_t src_y, uint32_t dst_x, uint32_t dst_y, const void *vdata) {
|
struct wlr_vk_texture *texture = vulkan_get_texture(wlr_texture);
|
||||||
return write_pixels(wlr_texture, stride, width, height, src_x, src_y,
|
struct wlr_buffer *buffer = raster->buffer;
|
||||||
dst_x, dst_y, vdata, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
|
||||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT);
|
void *data;
|
||||||
|
uint32_t format;
|
||||||
|
size_t stride;
|
||||||
|
if (!wlr_buffer_begin_data_ptr_access(buffer,
|
||||||
|
WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
if (format != texture->format->drm_format) {
|
||||||
|
ok = false;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rects_len = 0;
|
||||||
|
pixman_box32_t *rects = pixman_region32_rectangles(damage, &rects_len);
|
||||||
|
|
||||||
|
for (int i = 0; i < rects_len; i++) {
|
||||||
|
pixman_box32_t rect = rects[i];
|
||||||
|
uint32_t width = rect.x2 - rect.x1;
|
||||||
|
uint32_t height = rect.y2 - rect.y1;
|
||||||
|
|
||||||
|
// TODO: only map memory once
|
||||||
|
ok = write_pixels(wlr_texture, stride, width, height, rect.x1, rect.y1,
|
||||||
|
rect.x1, rect.y1, data, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT);
|
||||||
|
if (!ok) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
wlr_buffer_end_data_ptr_access(buffer);
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vulkan_texture_destroy(struct wlr_vk_texture *texture) {
|
void vulkan_texture_destroy(struct wlr_vk_texture *texture) {
|
||||||
if (!texture->renderer) {
|
struct wlr_vk_renderer *renderer =
|
||||||
free(texture);
|
vulkan_get_renderer(texture->wlr_texture.renderer);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// when we recorded a command to fill this image _this_ frame,
|
// when we recorded a command to fill this image _this_ frame,
|
||||||
// it has to be executed before the texture can be destroyed.
|
// it has to be executed before the texture can be destroyed.
|
||||||
// Add it to the renderer->destroy_textures list, destroying
|
// Add it to the renderer->destroy_textures list, destroying
|
||||||
// _after_ the stage command buffer has exectued
|
// _after_ the stage command buffer has exectued
|
||||||
if (texture->last_used == texture->renderer->frame) {
|
if (texture->last_used == renderer->frame) {
|
||||||
assert(texture->destroy_link.next == NULL); // not already inserted
|
assert(texture->destroy_link.next == NULL); // not already inserted
|
||||||
wl_list_insert(&texture->renderer->destroy_textures,
|
wl_list_insert(&renderer->destroy_textures,
|
||||||
&texture->destroy_link);
|
&texture->destroy_link);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -164,9 +197,9 @@ void vulkan_texture_destroy(struct wlr_vk_texture *texture) {
|
||||||
wl_list_remove(&texture->link);
|
wl_list_remove(&texture->link);
|
||||||
wl_list_remove(&texture->buffer_destroy.link);
|
wl_list_remove(&texture->buffer_destroy.link);
|
||||||
|
|
||||||
VkDevice dev = texture->renderer->dev->dev;
|
VkDevice dev = renderer->dev->dev;
|
||||||
if (texture->ds && texture->ds_pool) {
|
if (texture->ds && texture->ds_pool) {
|
||||||
vulkan_free_ds(texture->renderer, texture->ds_pool, texture->ds);
|
vulkan_free_ds(renderer, texture->ds_pool, texture->ds);
|
||||||
}
|
}
|
||||||
|
|
||||||
vkDestroyImageView(dev, texture->image_view, NULL);
|
vkDestroyImageView(dev, texture->image_view, NULL);
|
||||||
|
|
@ -191,7 +224,7 @@ static void vulkan_texture_unref(struct wlr_texture *wlr_texture) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wlr_texture_impl texture_impl = {
|
static const struct wlr_texture_impl texture_impl = {
|
||||||
.write_pixels = vulkan_texture_write_pixels,
|
.update_from_raster = vulkan_texture_update_from_raster,
|
||||||
.destroy = vulkan_texture_unref,
|
.destroy = vulkan_texture_unref,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -203,18 +236,16 @@ static struct wlr_vk_texture *vulkan_texture_create(
|
||||||
wlr_log_errno(WLR_ERROR, "Allocation failed");
|
wlr_log_errno(WLR_ERROR, "Allocation failed");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
wlr_texture_init(&texture->wlr_texture, &texture_impl, width, height);
|
wlr_texture_init(&texture->wlr_texture, &renderer->wlr_renderer,
|
||||||
texture->renderer = renderer;
|
&texture_impl, width, height);
|
||||||
wl_list_insert(&renderer->textures, &texture->link);
|
wl_list_insert(&renderer->textures, &texture->link);
|
||||||
wl_list_init(&texture->buffer_destroy.link);
|
wl_list_init(&texture->buffer_destroy.link);
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_texture *vulkan_texture_from_pixels(struct wlr_renderer *wlr_renderer,
|
static struct wlr_vk_texture *vulkan_texture_from_pixels(struct wlr_vk_renderer *renderer,
|
||||||
uint32_t drm_fmt, uint32_t stride, uint32_t width,
|
uint32_t drm_fmt, uint32_t stride, uint32_t width,
|
||||||
uint32_t height, const void *data) {
|
uint32_t height, const void *data) {
|
||||||
struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer);
|
|
||||||
|
|
||||||
VkResult res;
|
VkResult res;
|
||||||
VkDevice dev = renderer->dev->dev;
|
VkDevice dev = renderer->dev->dev;
|
||||||
|
|
||||||
|
|
@ -338,7 +369,7 @@ static struct wlr_texture *vulkan_texture_from_pixels(struct wlr_renderer *wlr_r
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return &texture->wlr_texture;
|
return texture;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
vulkan_texture_destroy(texture);
|
vulkan_texture_destroy(texture);
|
||||||
|
|
@ -573,7 +604,7 @@ error_image:
|
||||||
return VK_NULL_HANDLE;
|
return VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_texture *vulkan_texture_from_dmabuf(struct wlr_renderer *wlr_renderer,
|
static struct wlr_vk_texture *vulkan_texture_from_dmabuf(struct wlr_renderer *wlr_renderer,
|
||||||
struct wlr_dmabuf_attributes *attribs) {
|
struct wlr_dmabuf_attributes *attribs) {
|
||||||
struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer);
|
struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer);
|
||||||
|
|
||||||
|
|
@ -648,7 +679,7 @@ static struct wlr_texture *vulkan_texture_from_dmabuf(struct wlr_renderer *wlr_r
|
||||||
vkUpdateDescriptorSets(dev, 1, &ds_write, 0, NULL);
|
vkUpdateDescriptorSets(dev, 1, &ds_write, 0, NULL);
|
||||||
texture->dmabuf_imported = true;
|
texture->dmabuf_imported = true;
|
||||||
|
|
||||||
return &texture->wlr_texture;
|
return texture;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
vulkan_texture_destroy(texture);
|
vulkan_texture_destroy(texture);
|
||||||
|
|
@ -662,50 +693,69 @@ static void texture_handle_buffer_destroy(struct wl_listener *listener,
|
||||||
vulkan_texture_destroy(texture);
|
vulkan_texture_destroy(texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_texture *vulkan_texture_from_dmabuf_buffer(
|
static struct wlr_vk_texture *vulkan_texture_from_dmabuf_buffer(
|
||||||
struct wlr_vk_renderer *renderer, struct wlr_buffer *buffer,
|
struct wlr_vk_renderer *renderer, struct wlr_buffer *buffer,
|
||||||
struct wlr_dmabuf_attributes *dmabuf) {
|
struct wlr_dmabuf_attributes *dmabuf) {
|
||||||
struct wlr_vk_texture *texture;
|
struct wlr_vk_texture *texture;
|
||||||
wl_list_for_each(texture, &renderer->textures, link) {
|
wl_list_for_each(texture, &renderer->textures, link) {
|
||||||
if (texture->buffer == buffer) {
|
if (texture->buffer == buffer) {
|
||||||
wlr_buffer_lock(texture->buffer);
|
wlr_buffer_lock(texture->buffer);
|
||||||
return &texture->wlr_texture;
|
return texture;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_texture *wlr_texture =
|
texture = vulkan_texture_from_dmabuf(&renderer->wlr_renderer, dmabuf);
|
||||||
vulkan_texture_from_dmabuf(&renderer->wlr_renderer, dmabuf);
|
if (!texture) {
|
||||||
if (wlr_texture == NULL) {
|
return NULL;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
texture = vulkan_get_texture(wlr_texture);
|
|
||||||
texture->buffer = wlr_buffer_lock(buffer);
|
texture->buffer = wlr_buffer_lock(buffer);
|
||||||
|
|
||||||
texture->buffer_destroy.notify = texture_handle_buffer_destroy;
|
texture->buffer_destroy.notify = texture_handle_buffer_destroy;
|
||||||
wl_signal_add(&buffer->events.destroy, &texture->buffer_destroy);
|
wl_signal_add(&buffer->events.destroy, &texture->buffer_destroy);
|
||||||
|
|
||||||
return &texture->wlr_texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_texture *vulkan_texture_from_buffer(
|
struct wlr_vk_texture *vulkan_raster_upload(struct wlr_vk_renderer *renderer,
|
||||||
struct wlr_renderer *wlr_renderer,
|
struct wlr_raster *wlr_raster) {
|
||||||
struct wlr_buffer *buffer) {
|
struct wlr_texture *raster_texture;
|
||||||
struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer);
|
wl_list_for_each(raster_texture, &wlr_raster->sources, link) {
|
||||||
|
if (wlr_texture_is_vk(raster_texture)) {
|
||||||
|
struct wlr_vk_texture *vk_tex =
|
||||||
|
(struct wlr_vk_texture *)raster_texture;
|
||||||
|
if (vk_tex->wlr_texture.renderer != &renderer->wlr_renderer) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return vk_tex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_buffer *buffer = wlr_raster->buffer;
|
||||||
|
if (!wlr_raster->buffer) {
|
||||||
|
// we could possibly do a blit with another texture from another renderer,
|
||||||
|
// but this is unsupported currently.
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_vk_texture *texture = NULL;
|
||||||
|
|
||||||
void *data;
|
void *data;
|
||||||
uint32_t format;
|
uint32_t format;
|
||||||
size_t stride;
|
size_t stride;
|
||||||
struct wlr_dmabuf_attributes dmabuf;
|
struct wlr_dmabuf_attributes dmabuf;
|
||||||
if (wlr_buffer_get_dmabuf(buffer, &dmabuf)) {
|
if (wlr_buffer_get_dmabuf(buffer, &dmabuf)) {
|
||||||
return vulkan_texture_from_dmabuf_buffer(renderer, buffer, &dmabuf);
|
texture = vulkan_texture_from_dmabuf_buffer(renderer, buffer, &dmabuf);
|
||||||
} else if (wlr_buffer_begin_data_ptr_access(buffer,
|
} else if (wlr_buffer_begin_data_ptr_access(buffer,
|
||||||
WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) {
|
WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) {
|
||||||
struct wlr_texture *tex = vulkan_texture_from_pixels(wlr_renderer,
|
texture = vulkan_texture_from_pixels(renderer,
|
||||||
format, stride, buffer->width, buffer->height, data);
|
format, stride, buffer->width, buffer->height, data);
|
||||||
wlr_buffer_end_data_ptr_access(buffer);
|
wlr_buffer_end_data_ptr_access(buffer);
|
||||||
return tex;
|
|
||||||
} else {
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (texture) {
|
||||||
|
wlr_raster_attach(wlr_raster, &texture->wlr_texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <drm_fourcc.h>
|
||||||
#include <wlr/render/interface.h>
|
#include <wlr/render/interface.h>
|
||||||
#include <wlr/render/pixman.h>
|
#include <wlr/render/pixman.h>
|
||||||
#include <wlr/render/wlr_renderer.h>
|
#include <wlr/render/wlr_renderer.h>
|
||||||
|
|
@ -35,7 +36,8 @@ void wlr_renderer_init(struct wlr_renderer *renderer,
|
||||||
assert(impl->begin);
|
assert(impl->begin);
|
||||||
assert(impl->clear);
|
assert(impl->clear);
|
||||||
assert(impl->scissor);
|
assert(impl->scissor);
|
||||||
assert(impl->render_subtexture_with_matrix);
|
assert(impl->raster_upload);
|
||||||
|
assert(impl->render_subraster_with_matrix);
|
||||||
assert(impl->render_quad_with_matrix);
|
assert(impl->render_quad_with_matrix);
|
||||||
assert(impl->get_shm_texture_formats);
|
assert(impl->get_shm_texture_formats);
|
||||||
assert(impl->get_render_buffer_caps);
|
assert(impl->get_render_buffer_caps);
|
||||||
|
|
@ -113,39 +115,92 @@ void wlr_renderer_scissor(struct wlr_renderer *r, struct wlr_box *box) {
|
||||||
r->impl->scissor(r, box);
|
r->impl->scissor(r, box);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wlr_render_texture(struct wlr_renderer *r, struct wlr_texture *texture,
|
bool wlr_renderer_raster_upload(struct wlr_renderer *r,
|
||||||
|
struct wlr_raster *raster) {
|
||||||
|
return r->impl->raster_upload(r, raster);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wlr_render_raster(struct wlr_renderer *r, struct wlr_raster *raster,
|
||||||
const float projection[static 9], int x, int y, float alpha) {
|
const float projection[static 9], int x, int y, float alpha) {
|
||||||
struct wlr_box box = {
|
struct wlr_box box = {
|
||||||
.x = x,
|
.x = x,
|
||||||
.y = y,
|
.y = y,
|
||||||
.width = texture->width,
|
.width = raster->width,
|
||||||
.height = texture->height,
|
.height = raster->height,
|
||||||
};
|
};
|
||||||
|
|
||||||
float matrix[9];
|
float matrix[9];
|
||||||
wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0,
|
wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0,
|
||||||
projection);
|
projection);
|
||||||
|
|
||||||
return wlr_render_texture_with_matrix(r, texture, matrix, alpha);
|
return wlr_render_raster_with_matrix(r, raster, matrix, alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wlr_render_texture_with_matrix(struct wlr_renderer *r,
|
bool wlr_render_raster_with_matrix(struct wlr_renderer *r,
|
||||||
struct wlr_texture *texture, const float matrix[static 9],
|
struct wlr_raster *raster, const float matrix[static 9],
|
||||||
float alpha) {
|
float alpha) {
|
||||||
struct wlr_fbox box = {
|
struct wlr_fbox box = {
|
||||||
.x = 0,
|
.x = 0,
|
||||||
.y = 0,
|
.y = 0,
|
||||||
.width = texture->width,
|
.width = raster->width,
|
||||||
.height = texture->height,
|
.height = raster->height,
|
||||||
};
|
};
|
||||||
return wlr_render_subtexture_with_matrix(r, texture, &box, matrix, alpha);
|
return wlr_render_subraster_with_matrix(r, raster, &box, matrix, alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wlr_render_subtexture_with_matrix(struct wlr_renderer *r,
|
static bool try_single_pixel(struct wlr_buffer *buffer,
|
||||||
struct wlr_texture *texture, const struct wlr_fbox *box,
|
float color[static 4], const struct wlr_fbox *box, float alpha) {
|
||||||
|
if (box->width != 1.f || box->height != 1.f ||
|
||||||
|
box->x < 0.f || box->y < 0.f ||
|
||||||
|
box->x >= buffer->width || box->y >= buffer->height) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t x = floor(box->x);
|
||||||
|
uint32_t y = floor(box->y);
|
||||||
|
|
||||||
|
if (box->x != (float)x || box->y != (float)y) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *data;
|
||||||
|
uint32_t format;
|
||||||
|
size_t stride;
|
||||||
|
if (!wlr_buffer_begin_data_ptr_access(buffer,
|
||||||
|
WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format != DRM_FORMAT_ARGB8888) {
|
||||||
|
wlr_buffer_end_data_ptr_access(buffer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t pixel_stride = stride / buffer->width;
|
||||||
|
uint8_t *data_color = &((uint8_t *)data)[pixel_stride * x + stride * y];
|
||||||
|
color[0] = data_color[3] * alpha / 255.f;
|
||||||
|
color[1] = data_color[2] * alpha / 255.f;
|
||||||
|
color[2] = data_color[1] * alpha / 255.f;
|
||||||
|
color[3] = data_color[0] * alpha / 255.f;
|
||||||
|
|
||||||
|
wlr_buffer_end_data_ptr_access(buffer);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wlr_render_subraster_with_matrix(struct wlr_renderer *r,
|
||||||
|
struct wlr_raster *raster, const struct wlr_fbox *box,
|
||||||
const float matrix[static 9], float alpha) {
|
const float matrix[static 9], float alpha) {
|
||||||
assert(r->rendering);
|
assert(r->rendering);
|
||||||
return r->impl->render_subtexture_with_matrix(r, texture,
|
|
||||||
|
float color[4];
|
||||||
|
if (raster->buffer &&
|
||||||
|
try_single_pixel(raster->buffer, (float *)&color, box, alpha)) {
|
||||||
|
wlr_render_quad_with_matrix(r, color, matrix);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r->impl->render_subraster_with_matrix(r, raster,
|
||||||
box, matrix, alpha);
|
box, matrix, alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,80 +4,49 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <wlr/render/interface.h>
|
#include <wlr/render/interface.h>
|
||||||
#include <wlr/render/wlr_texture.h>
|
#include <wlr/render/wlr_texture.h>
|
||||||
|
#include <wlr/types/wlr_raster.h>
|
||||||
#include "types/wlr_buffer.h"
|
#include "types/wlr_buffer.h"
|
||||||
|
|
||||||
void wlr_texture_init(struct wlr_texture *texture,
|
void wlr_texture_init(struct wlr_texture *texture, struct wlr_renderer *renderer,
|
||||||
const struct wlr_texture_impl *impl, uint32_t width, uint32_t height) {
|
const struct wlr_texture_impl *impl, uint32_t width, uint32_t height) {
|
||||||
|
assert(renderer);
|
||||||
|
|
||||||
memset(texture, 0, sizeof(*texture));
|
memset(texture, 0, sizeof(*texture));
|
||||||
|
texture->renderer = renderer;
|
||||||
texture->impl = impl;
|
texture->impl = impl;
|
||||||
texture->width = width;
|
texture->width = width;
|
||||||
texture->height = height;
|
texture->height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_texture_destroy(struct wlr_texture *texture) {
|
void wlr_texture_destroy(struct wlr_texture *texture) {
|
||||||
if (texture && texture->impl && texture->impl->destroy) {
|
if (!texture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture->raster) {
|
||||||
|
wlr_raster_detach(texture->raster, texture);
|
||||||
|
texture->raster = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture->impl && texture->impl->destroy) {
|
||||||
texture->impl->destroy(texture);
|
texture->impl->destroy(texture);
|
||||||
} else {
|
} else {
|
||||||
free(texture);
|
free(texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_texture *wlr_texture_from_pixels(struct wlr_renderer *renderer,
|
bool wlr_texture_update_from_raster(struct wlr_texture *texture,
|
||||||
uint32_t fmt, uint32_t stride, uint32_t width, uint32_t height,
|
struct wlr_raster *raster, pixman_region32_t *damage) {
|
||||||
const void *data) {
|
if (!texture->impl->update_from_raster) {
|
||||||
assert(width > 0);
|
|
||||||
assert(height > 0);
|
|
||||||
assert(stride > 0);
|
|
||||||
assert(data);
|
|
||||||
|
|
||||||
struct wlr_readonly_data_buffer *buffer =
|
|
||||||
readonly_data_buffer_create(fmt, stride, width, height, data);
|
|
||||||
if (buffer == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_texture *texture =
|
|
||||||
wlr_texture_from_buffer(renderer, &buffer->base);
|
|
||||||
|
|
||||||
// By this point, the renderer should have locked the buffer if it still
|
|
||||||
// needs to access it in the future.
|
|
||||||
readonly_data_buffer_drop(buffer);
|
|
||||||
|
|
||||||
return texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_texture *wlr_texture_from_dmabuf(struct wlr_renderer *renderer,
|
|
||||||
struct wlr_dmabuf_attributes *attribs) {
|
|
||||||
struct wlr_dmabuf_buffer *buffer = dmabuf_buffer_create(attribs);
|
|
||||||
if (buffer == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_texture *texture =
|
|
||||||
wlr_texture_from_buffer(renderer, &buffer->base);
|
|
||||||
|
|
||||||
// By this point, the renderer should have locked the buffer if it still
|
|
||||||
// needs to access it in the future.
|
|
||||||
dmabuf_buffer_drop(buffer);
|
|
||||||
|
|
||||||
return texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_texture *wlr_texture_from_buffer(struct wlr_renderer *renderer,
|
|
||||||
struct wlr_buffer *buffer) {
|
|
||||||
if (!renderer->impl->texture_from_buffer) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return renderer->impl->texture_from_buffer(renderer, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool wlr_texture_write_pixels(struct wlr_texture *texture,
|
|
||||||
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,
|
|
||||||
const void *data) {
|
|
||||||
if (!texture->impl->write_pixels) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return texture->impl->write_pixels(texture, stride, width, height,
|
if (texture->width != raster->width || texture->height != raster->height) {
|
||||||
src_x, src_y, dst_x, dst_y, data);
|
return false;
|
||||||
|
}
|
||||||
|
const pixman_box32_t *extents = pixman_region32_extents(damage);
|
||||||
|
if (extents->x1 < 0 || extents->y1 < 0 || extents->x2 > (int32_t)raster->width ||
|
||||||
|
extents->y2 > (int32_t)raster->height) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return texture->impl->update_from_raster(texture, raster, damage);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -343,12 +343,12 @@ static struct tinywl_view *desktop_view_at(
|
||||||
* surface in the surface tree of a tinywl_view. */
|
* surface in the surface tree of a tinywl_view. */
|
||||||
struct wlr_scene_node *node = wlr_scene_node_at(
|
struct wlr_scene_node *node = wlr_scene_node_at(
|
||||||
&server->scene->tree.node, lx, ly, sx, sy);
|
&server->scene->tree.node, lx, ly, sx, sy);
|
||||||
if (node == NULL || node->type != WLR_SCENE_NODE_BUFFER) {
|
if (node == NULL || node->type != WLR_SCENE_NODE_RASTER) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node);
|
struct wlr_scene_raster *scene_raster = wlr_scene_raster_from_node(node);
|
||||||
struct wlr_scene_surface *scene_surface =
|
struct wlr_scene_surface *scene_surface =
|
||||||
wlr_scene_surface_from_buffer(scene_buffer);
|
wlr_scene_surface_from_raster(scene_raster);
|
||||||
if (!scene_surface) {
|
if (!scene_surface) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -853,7 +853,7 @@ int main(int argc, char *argv[]) {
|
||||||
* to dig your fingers in and play with their behavior if you want. Note that
|
* to dig your fingers in and play with their behavior if you want. Note that
|
||||||
* the clients cannot set the selection directly without compositor approval,
|
* the clients cannot set the selection directly without compositor approval,
|
||||||
* see the handling of the request_set_selection event below.*/
|
* see the handling of the request_set_selection event below.*/
|
||||||
wlr_compositor_create(server.wl_display, server.renderer);
|
wlr_compositor_create(server.wl_display);
|
||||||
wlr_subcompositor_create(server.wl_display);
|
wlr_subcompositor_create(server.wl_display);
|
||||||
wlr_data_device_manager_create(server.wl_display);
|
wlr_data_device_manager_create(server.wl_display);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ wlr_files += files(
|
||||||
'wlr_presentation_time.c',
|
'wlr_presentation_time.c',
|
||||||
'wlr_primary_selection_v1.c',
|
'wlr_primary_selection_v1.c',
|
||||||
'wlr_primary_selection.c',
|
'wlr_primary_selection.c',
|
||||||
|
'wlr_raster.c',
|
||||||
'wlr_region.c',
|
'wlr_region.c',
|
||||||
'wlr_relative_pointer_v1.c',
|
'wlr_relative_pointer_v1.c',
|
||||||
'wlr_screencopy_v1.c',
|
'wlr_screencopy_v1.c',
|
||||||
|
|
|
||||||
|
|
@ -93,11 +93,7 @@ static void output_cursor_render(struct wlr_output_cursor *cursor,
|
||||||
struct wlr_renderer *renderer = cursor->output->renderer;
|
struct wlr_renderer *renderer = cursor->output->renderer;
|
||||||
assert(renderer);
|
assert(renderer);
|
||||||
|
|
||||||
struct wlr_texture *texture = cursor->texture;
|
if (!cursor->raster) {
|
||||||
if (cursor->surface != NULL) {
|
|
||||||
texture = wlr_surface_get_texture(cursor->surface);
|
|
||||||
}
|
|
||||||
if (texture == NULL) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -121,7 +117,7 @@ static void output_cursor_render(struct wlr_output_cursor *cursor,
|
||||||
pixman_box32_t *rects = pixman_region32_rectangles(&surface_damage, &nrects);
|
pixman_box32_t *rects = pixman_region32_rectangles(&surface_damage, &nrects);
|
||||||
for (int i = 0; i < nrects; ++i) {
|
for (int i = 0; i < nrects; ++i) {
|
||||||
output_scissor(cursor->output, &rects[i]);
|
output_scissor(cursor->output, &rects[i]);
|
||||||
wlr_render_texture_with_matrix(renderer, texture, matrix, 1.0f);
|
wlr_render_raster_with_matrix(renderer, cursor->raster, matrix, 1.0f);
|
||||||
}
|
}
|
||||||
wlr_renderer_scissor(renderer, NULL);
|
wlr_renderer_scissor(renderer, NULL);
|
||||||
|
|
||||||
|
|
@ -234,29 +230,28 @@ static struct wlr_buffer *render_cursor_buffer(struct wlr_output_cursor *cursor)
|
||||||
|
|
||||||
float scale = output->scale;
|
float scale = output->scale;
|
||||||
enum wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
enum wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||||
struct wlr_texture *texture = cursor->texture;
|
|
||||||
if (cursor->surface != NULL) {
|
if (cursor->surface != NULL) {
|
||||||
texture = wlr_surface_get_texture(cursor->surface);
|
|
||||||
scale = cursor->surface->current.scale;
|
scale = cursor->surface->current.scale;
|
||||||
transform = cursor->surface->current.transform;
|
transform = cursor->surface->current.transform;
|
||||||
}
|
}
|
||||||
if (texture == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_allocator *allocator = output->allocator;
|
struct wlr_allocator *allocator = output->allocator;
|
||||||
struct wlr_renderer *renderer = output->renderer;
|
struct wlr_renderer *renderer = output->renderer;
|
||||||
assert(allocator != NULL && renderer != NULL);
|
assert(allocator != NULL && renderer != NULL);
|
||||||
|
|
||||||
int width = texture->width;
|
if (!cursor->raster) {
|
||||||
int height = texture->height;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int width = cursor->raster->width;
|
||||||
|
int height = cursor->raster->height;
|
||||||
if (output->impl->get_cursor_size) {
|
if (output->impl->get_cursor_size) {
|
||||||
// Apply hardware limitations on buffer size
|
// Apply hardware limitations on buffer size
|
||||||
output->impl->get_cursor_size(cursor->output, &width, &height);
|
output->impl->get_cursor_size(cursor->output, &width, &height);
|
||||||
if ((int)texture->width > width || (int)texture->height > height) {
|
if ((int)cursor->raster->width > width || (int)cursor->raster->height > height) {
|
||||||
wlr_log(WLR_DEBUG, "Cursor texture too large (%dx%d), "
|
wlr_log(WLR_DEBUG, "Cursor raster too large (%dx%d), "
|
||||||
"exceeds hardware limitations (%dx%d)", texture->width,
|
"exceeds hardware limitations (%dx%d)", cursor->raster->width,
|
||||||
texture->height, width, height);
|
cursor->raster->height, width, height);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -288,8 +283,8 @@ static struct wlr_buffer *render_cursor_buffer(struct wlr_output_cursor *cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_box cursor_box = {
|
struct wlr_box cursor_box = {
|
||||||
.width = texture->width * output->scale / scale,
|
.width = cursor->raster->width * output->scale / scale,
|
||||||
.height = texture->height * output->scale / scale,
|
.height = cursor->raster->height * output->scale / scale,
|
||||||
};
|
};
|
||||||
|
|
||||||
float output_matrix[9];
|
float output_matrix[9];
|
||||||
|
|
@ -317,7 +312,7 @@ static struct wlr_buffer *render_cursor_buffer(struct wlr_output_cursor *cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_renderer_clear(renderer, (float[]){ 0.0, 0.0, 0.0, 0.0 });
|
wlr_renderer_clear(renderer, (float[]){ 0.0, 0.0, 0.0, 0.0 });
|
||||||
wlr_render_texture_with_matrix(renderer, texture, matrix, 1.0);
|
wlr_render_raster_with_matrix(renderer, cursor->raster, matrix, 1.0);
|
||||||
|
|
||||||
wlr_renderer_end(renderer);
|
wlr_renderer_end(renderer);
|
||||||
|
|
||||||
|
|
@ -337,24 +332,16 @@ static bool output_cursor_attempt_hardware(struct wlr_output_cursor *cursor) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_texture *texture = cursor->texture;
|
|
||||||
if (cursor->surface != NULL) {
|
|
||||||
// TODO: try using the surface buffer directly
|
|
||||||
texture = wlr_surface_get_texture(cursor->surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the cursor was hidden or was a software cursor, the hardware
|
// If the cursor was hidden or was a software cursor, the hardware
|
||||||
// cursor position is outdated
|
// cursor position is outdated
|
||||||
output->impl->move_cursor(cursor->output,
|
output->impl->move_cursor(cursor->output,
|
||||||
(int)cursor->x, (int)cursor->y);
|
(int)cursor->x, (int)cursor->y);
|
||||||
|
|
||||||
struct wlr_buffer *buffer = NULL;
|
struct wlr_buffer *buffer = NULL;
|
||||||
if (texture != NULL) {
|
buffer = render_cursor_buffer(cursor);
|
||||||
buffer = render_cursor_buffer(cursor);
|
if (buffer == NULL) {
|
||||||
if (buffer == NULL) {
|
wlr_log(WLR_ERROR, "Failed to render cursor buffer");
|
||||||
wlr_log(WLR_ERROR, "Failed to render cursor buffer");
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_box hotspot = {
|
struct wlr_box hotspot = {
|
||||||
|
|
@ -376,24 +363,20 @@ static bool output_cursor_attempt_hardware(struct wlr_output_cursor *cursor) {
|
||||||
bool wlr_output_cursor_set_image(struct wlr_output_cursor *cursor,
|
bool wlr_output_cursor_set_image(struct wlr_output_cursor *cursor,
|
||||||
const uint8_t *pixels, int32_t stride, uint32_t width, uint32_t height,
|
const uint8_t *pixels, int32_t stride, uint32_t width, uint32_t height,
|
||||||
int32_t hotspot_x, int32_t hotspot_y) {
|
int32_t hotspot_x, int32_t hotspot_y) {
|
||||||
struct wlr_buffer *buffer = NULL;
|
struct wlr_raster *raster = NULL;
|
||||||
|
|
||||||
if (pixels) {
|
if (pixels) {
|
||||||
struct wlr_readonly_data_buffer *ro_buffer = readonly_data_buffer_create(
|
raster = wlr_raster_from_pixels(DRM_FORMAT_ARGB8888,
|
||||||
DRM_FORMAT_ARGB8888, stride, width, height, pixels);
|
stride, width, height, pixels);
|
||||||
if (ro_buffer == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
buffer = &ro_buffer->base;
|
|
||||||
}
|
}
|
||||||
bool ok = wlr_output_cursor_set_buffer(cursor, buffer, hotspot_x, hotspot_y);
|
bool ok = wlr_output_cursor_set_raster(cursor, raster, hotspot_x, hotspot_y);
|
||||||
|
|
||||||
wlr_buffer_drop(buffer);
|
wlr_raster_unlock(raster);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wlr_output_cursor_set_buffer(struct wlr_output_cursor *cursor,
|
bool wlr_output_cursor_set_raster(struct wlr_output_cursor *cursor,
|
||||||
struct wlr_buffer *buffer, int32_t hotspot_x, int32_t hotspot_y) {
|
struct wlr_raster *raster, int32_t hotspot_x, int32_t hotspot_y) {
|
||||||
struct wlr_renderer *renderer = cursor->output->renderer;
|
struct wlr_renderer *renderer = cursor->output->renderer;
|
||||||
if (!renderer) {
|
if (!renderer) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -401,9 +384,9 @@ bool wlr_output_cursor_set_buffer(struct wlr_output_cursor *cursor,
|
||||||
|
|
||||||
output_cursor_reset(cursor);
|
output_cursor_reset(cursor);
|
||||||
|
|
||||||
if (buffer != NULL) {
|
if (raster) {
|
||||||
cursor->width = buffer->width;
|
cursor->width = raster->width;
|
||||||
cursor->height = buffer->height;
|
cursor->height = raster->height;
|
||||||
} else {
|
} else {
|
||||||
cursor->width = 0;
|
cursor->width = 0;
|
||||||
cursor->height = 0;
|
cursor->height = 0;
|
||||||
|
|
@ -414,16 +397,12 @@ bool wlr_output_cursor_set_buffer(struct wlr_output_cursor *cursor,
|
||||||
|
|
||||||
output_cursor_update_visible(cursor);
|
output_cursor_update_visible(cursor);
|
||||||
|
|
||||||
wlr_texture_destroy(cursor->texture);
|
wlr_raster_unlock(cursor->raster);
|
||||||
cursor->texture = NULL;
|
cursor->raster = NULL;
|
||||||
|
|
||||||
cursor->enabled = false;
|
cursor->enabled = raster;
|
||||||
if (buffer != NULL) {
|
if (raster) {
|
||||||
cursor->texture = wlr_texture_from_buffer(renderer, buffer);
|
cursor->raster = wlr_raster_lock(raster);
|
||||||
if (cursor->texture == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
cursor->enabled = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output_cursor_attempt_hardware(cursor)) {
|
if (output_cursor_attempt_hardware(cursor)) {
|
||||||
|
|
@ -442,9 +421,16 @@ static void output_cursor_commit(struct wlr_output_cursor *cursor,
|
||||||
output_cursor_damage_whole(cursor);
|
output_cursor_damage_whole(cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wlr_raster_unlock(cursor->raster);
|
||||||
|
cursor->raster = NULL;
|
||||||
|
|
||||||
struct wlr_surface *surface = cursor->surface;
|
struct wlr_surface *surface = cursor->surface;
|
||||||
assert(surface != NULL);
|
assert(surface != NULL);
|
||||||
|
|
||||||
|
if (surface->raster) {
|
||||||
|
cursor->raster = wlr_raster_lock(surface->raster);
|
||||||
|
}
|
||||||
|
|
||||||
// Some clients commit a cursor surface with a NULL buffer to hide it.
|
// Some clients commit a cursor surface with a NULL buffer to hide it.
|
||||||
cursor->enabled = wlr_surface_has_buffer(surface);
|
cursor->enabled = wlr_surface_has_buffer(surface);
|
||||||
cursor->width = surface->current.width * cursor->output->scale;
|
cursor->width = surface->current.width * cursor->output->scale;
|
||||||
|
|
@ -589,7 +575,7 @@ void wlr_output_cursor_destroy(struct wlr_output_cursor *cursor) {
|
||||||
output_set_hardware_cursor(cursor->output, NULL, 0, 0);
|
output_set_hardware_cursor(cursor->output, NULL, 0, 0);
|
||||||
cursor->output->hardware_cursor = NULL;
|
cursor->output->hardware_cursor = NULL;
|
||||||
}
|
}
|
||||||
wlr_texture_destroy(cursor->texture);
|
wlr_raster_unlock(cursor->raster);
|
||||||
wl_list_remove(&cursor->link);
|
wl_list_remove(&cursor->link);
|
||||||
free(cursor);
|
free(cursor);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,9 +81,9 @@ static void subsurface_tree_reconfigure(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prev != NULL) {
|
if (prev != NULL) {
|
||||||
wlr_scene_node_place_above(&subsurface_tree->scene_surface->buffer->node, prev);
|
wlr_scene_node_place_above(&subsurface_tree->scene_surface->raster->node, prev);
|
||||||
}
|
}
|
||||||
prev = &subsurface_tree->scene_surface->buffer->node;
|
prev = &subsurface_tree->scene_surface->raster->node;
|
||||||
|
|
||||||
wl_list_for_each(subsurface, &surface->current.subsurfaces_above,
|
wl_list_for_each(subsurface, &surface->current.subsurfaces_above,
|
||||||
current.link) {
|
current.link) {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
#include <wlr/types/wlr_presentation_time.h>
|
#include <wlr/types/wlr_presentation_time.h>
|
||||||
#include "types/wlr_scene.h"
|
#include "types/wlr_scene.h"
|
||||||
|
|
||||||
static void handle_scene_buffer_output_enter(
|
static void handle_scene_raster_output_enter(
|
||||||
struct wl_listener *listener, void *data) {
|
struct wl_listener *listener, void *data) {
|
||||||
struct wlr_scene_surface *surface =
|
struct wlr_scene_surface *surface =
|
||||||
wl_container_of(listener, surface, output_enter);
|
wl_container_of(listener, surface, output_enter);
|
||||||
|
|
@ -12,7 +12,7 @@ static void handle_scene_buffer_output_enter(
|
||||||
wlr_surface_send_enter(surface->surface, output->output);
|
wlr_surface_send_enter(surface->surface, output->output);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_scene_buffer_output_leave(
|
static void handle_scene_raster_output_leave(
|
||||||
struct wl_listener *listener, void *data) {
|
struct wl_listener *listener, void *data) {
|
||||||
struct wlr_scene_surface *surface =
|
struct wlr_scene_surface *surface =
|
||||||
wl_container_of(listener, surface, output_leave);
|
wl_container_of(listener, surface, output_leave);
|
||||||
|
|
@ -21,14 +21,14 @@ static void handle_scene_buffer_output_leave(
|
||||||
wlr_surface_send_leave(surface->surface, output->output);
|
wlr_surface_send_leave(surface->surface, output->output);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_scene_buffer_output_present(
|
static void handle_scene_raster_output_present(
|
||||||
struct wl_listener *listener, void *data) {
|
struct wl_listener *listener, void *data) {
|
||||||
struct wlr_scene_surface *surface =
|
struct wlr_scene_surface *surface =
|
||||||
wl_container_of(listener, surface, output_present);
|
wl_container_of(listener, surface, output_present);
|
||||||
struct wlr_scene_output *scene_output = data;
|
struct wlr_scene_output *scene_output = data;
|
||||||
|
|
||||||
if (surface->buffer->primary_output == scene_output) {
|
if (surface->raster->primary_output == scene_output) {
|
||||||
struct wlr_scene *root = scene_node_get_root(&surface->buffer->node);
|
struct wlr_scene *root = scene_node_get_root(&surface->raster->node);
|
||||||
struct wlr_presentation *presentation = root->presentation;
|
struct wlr_presentation *presentation = root->presentation;
|
||||||
|
|
||||||
if (presentation) {
|
if (presentation) {
|
||||||
|
|
@ -38,7 +38,7 @@ static void handle_scene_buffer_output_present(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_scene_buffer_frame_done(
|
static void handle_scene_raster_frame_done(
|
||||||
struct wl_listener *listener, void *data) {
|
struct wl_listener *listener, void *data) {
|
||||||
struct wlr_scene_surface *surface =
|
struct wlr_scene_surface *surface =
|
||||||
wl_container_of(listener, surface, frame_done);
|
wl_container_of(listener, surface, frame_done);
|
||||||
|
|
@ -52,25 +52,27 @@ static void scene_surface_handle_surface_destroy(
|
||||||
struct wlr_scene_surface *surface =
|
struct wlr_scene_surface *surface =
|
||||||
wl_container_of(listener, surface, surface_destroy);
|
wl_container_of(listener, surface, surface_destroy);
|
||||||
|
|
||||||
wlr_scene_node_destroy(&surface->buffer->node);
|
wlr_scene_node_destroy(&surface->raster->node);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_buffer_with_surface_state(struct wlr_scene_buffer *scene_buffer,
|
static void set_raster_with_surface_state(struct wlr_scene_raster *scene_raster,
|
||||||
struct wlr_surface *surface) {
|
struct wlr_surface *surface) {
|
||||||
struct wlr_surface_state *state = &surface->current;
|
struct wlr_surface_state *state = &surface->current;
|
||||||
|
|
||||||
struct wlr_fbox src_box;
|
struct wlr_fbox src_box;
|
||||||
wlr_surface_get_buffer_source_box(surface, &src_box);
|
wlr_surface_get_buffer_source_box(surface, &src_box);
|
||||||
wlr_scene_buffer_set_source_box(scene_buffer, &src_box);
|
wlr_scene_raster_set_source_box(scene_raster, &src_box);
|
||||||
|
|
||||||
wlr_scene_buffer_set_dest_size(scene_buffer, state->width, state->height);
|
wlr_scene_raster_set_dest_size(scene_raster, state->width, state->height);
|
||||||
wlr_scene_buffer_set_transform(scene_buffer, state->transform);
|
wlr_scene_raster_set_transform(scene_raster, state->transform);
|
||||||
|
|
||||||
if (surface->buffer) {
|
struct wlr_raster *raster = surface->raster;
|
||||||
wlr_scene_buffer_set_buffer_with_damage(scene_buffer,
|
|
||||||
&surface->buffer->base, &surface->buffer_damage);
|
if (raster) {
|
||||||
|
wlr_scene_raster_set_raster_with_damage(scene_raster,
|
||||||
|
raster, &surface->buffer_damage);
|
||||||
} else {
|
} else {
|
||||||
wlr_scene_buffer_set_buffer(scene_buffer, NULL);
|
wlr_scene_raster_set_raster(scene_raster, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -78,27 +80,27 @@ static void handle_scene_surface_surface_commit(
|
||||||
struct wl_listener *listener, void *data) {
|
struct wl_listener *listener, void *data) {
|
||||||
struct wlr_scene_surface *surface =
|
struct wlr_scene_surface *surface =
|
||||||
wl_container_of(listener, surface, surface_commit);
|
wl_container_of(listener, surface, surface_commit);
|
||||||
struct wlr_scene_buffer *scene_buffer = surface->buffer;
|
struct wlr_scene_raster *scene_raster = surface->raster;
|
||||||
|
|
||||||
set_buffer_with_surface_state(scene_buffer, surface->surface);
|
set_raster_with_surface_state(scene_raster, surface->surface);
|
||||||
|
|
||||||
// Even if the surface hasn't submitted damage, schedule a new frame if
|
// Even if the surface hasn't submitted damage, schedule a new frame if
|
||||||
// the client has requested a wl_surface.frame callback. Check if the node
|
// the client has requested a wl_surface.frame callback. Check if the node
|
||||||
// is visible. If not, the client will never receive a frame_done event
|
// is visible. If not, the client will never receive a frame_done event
|
||||||
// anyway so it doesn't make sense to schedule here.
|
// anyway so it doesn't make sense to schedule here.
|
||||||
int lx, ly;
|
int lx, ly;
|
||||||
bool enabled = wlr_scene_node_coords(&scene_buffer->node, &lx, &ly);
|
bool enabled = wlr_scene_node_coords(&scene_raster->node, &lx, &ly);
|
||||||
|
|
||||||
if (!wl_list_empty(&surface->surface->current.frame_callback_list) &&
|
if (!wl_list_empty(&surface->surface->current.frame_callback_list) &&
|
||||||
surface->buffer->primary_output != NULL && enabled) {
|
surface->raster->primary_output != NULL && enabled) {
|
||||||
wlr_output_schedule_frame(surface->buffer->primary_output->output);
|
wlr_output_schedule_frame(surface->raster->primary_output->output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool scene_buffer_point_accepts_input(struct wlr_scene_buffer *scene_buffer,
|
static bool scene_raster_point_accepts_input(struct wlr_scene_raster *scene_raster,
|
||||||
int sx, int sy) {
|
int sx, int sy) {
|
||||||
struct wlr_scene_surface *scene_surface =
|
struct wlr_scene_surface *scene_surface =
|
||||||
wlr_scene_surface_from_buffer(scene_buffer);
|
wlr_scene_surface_from_raster(scene_raster);
|
||||||
|
|
||||||
return wlr_surface_point_accepts_input(scene_surface->surface, sx, sy);
|
return wlr_surface_point_accepts_input(scene_surface->surface, sx, sy);
|
||||||
}
|
}
|
||||||
|
|
@ -123,10 +125,10 @@ static const struct wlr_addon_interface surface_addon_impl = {
|
||||||
.destroy = surface_addon_destroy,
|
.destroy = surface_addon_destroy,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_scene_surface *wlr_scene_surface_from_buffer(
|
struct wlr_scene_surface *wlr_scene_surface_from_raster(
|
||||||
struct wlr_scene_buffer *scene_buffer) {
|
struct wlr_scene_raster *scene_raster) {
|
||||||
struct wlr_addon *addon = wlr_addon_find(&scene_buffer->node.addons,
|
struct wlr_addon *addon = wlr_addon_find(&scene_raster->node.addons,
|
||||||
scene_buffer, &surface_addon_impl);
|
scene_raster, &surface_addon_impl);
|
||||||
if (!addon) {
|
if (!addon) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -142,27 +144,27 @@ struct wlr_scene_surface *wlr_scene_surface_create(struct wlr_scene_tree *parent
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_create(parent, NULL);
|
struct wlr_scene_raster *scene_raster = wlr_scene_raster_create(parent, NULL);
|
||||||
if (!scene_buffer) {
|
if (!scene_raster) {
|
||||||
free(surface);
|
free(surface);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
surface->buffer = scene_buffer;
|
surface->raster = scene_raster;
|
||||||
surface->surface = wlr_surface;
|
surface->surface = wlr_surface;
|
||||||
scene_buffer->point_accepts_input = scene_buffer_point_accepts_input;
|
scene_raster->point_accepts_input = scene_raster_point_accepts_input;
|
||||||
|
|
||||||
surface->output_enter.notify = handle_scene_buffer_output_enter;
|
surface->output_enter.notify = handle_scene_raster_output_enter;
|
||||||
wl_signal_add(&scene_buffer->events.output_enter, &surface->output_enter);
|
wl_signal_add(&scene_raster->events.output_enter, &surface->output_enter);
|
||||||
|
|
||||||
surface->output_leave.notify = handle_scene_buffer_output_leave;
|
surface->output_leave.notify = handle_scene_raster_output_leave;
|
||||||
wl_signal_add(&scene_buffer->events.output_leave, &surface->output_leave);
|
wl_signal_add(&scene_raster->events.output_leave, &surface->output_leave);
|
||||||
|
|
||||||
surface->output_present.notify = handle_scene_buffer_output_present;
|
surface->output_present.notify = handle_scene_raster_output_present;
|
||||||
wl_signal_add(&scene_buffer->events.output_present, &surface->output_present);
|
wl_signal_add(&scene_raster->events.output_present, &surface->output_present);
|
||||||
|
|
||||||
surface->frame_done.notify = handle_scene_buffer_frame_done;
|
surface->frame_done.notify = handle_scene_raster_frame_done;
|
||||||
wl_signal_add(&scene_buffer->events.frame_done, &surface->frame_done);
|
wl_signal_add(&scene_raster->events.frame_done, &surface->frame_done);
|
||||||
|
|
||||||
surface->surface_destroy.notify = scene_surface_handle_surface_destroy;
|
surface->surface_destroy.notify = scene_surface_handle_surface_destroy;
|
||||||
wl_signal_add(&wlr_surface->events.destroy, &surface->surface_destroy);
|
wl_signal_add(&wlr_surface->events.destroy, &surface->surface_destroy);
|
||||||
|
|
@ -170,10 +172,10 @@ struct wlr_scene_surface *wlr_scene_surface_create(struct wlr_scene_tree *parent
|
||||||
surface->surface_commit.notify = handle_scene_surface_surface_commit;
|
surface->surface_commit.notify = handle_scene_surface_surface_commit;
|
||||||
wl_signal_add(&wlr_surface->events.commit, &surface->surface_commit);
|
wl_signal_add(&wlr_surface->events.commit, &surface->surface_commit);
|
||||||
|
|
||||||
wlr_addon_init(&surface->addon, &scene_buffer->node.addons,
|
wlr_addon_init(&surface->addon, &scene_raster->node.addons,
|
||||||
scene_buffer, &surface_addon_impl);
|
scene_raster, &surface_addon_impl);
|
||||||
|
|
||||||
set_buffer_with_surface_state(scene_buffer, wlr_surface);
|
set_raster_with_surface_state(scene_raster, wlr_surface);
|
||||||
|
|
||||||
return surface;
|
return surface;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,10 @@ static struct wlr_scene_rect *scene_rect_from_node(
|
||||||
return (struct wlr_scene_rect *)node;
|
return (struct wlr_scene_rect *)node;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_scene_buffer *wlr_scene_buffer_from_node(
|
struct wlr_scene_raster *wlr_scene_raster_from_node(
|
||||||
struct wlr_scene_node *node) {
|
struct wlr_scene_node *node) {
|
||||||
assert(node->type == WLR_SCENE_NODE_BUFFER);
|
assert(node->type == WLR_SCENE_NODE_RASTER);
|
||||||
return (struct wlr_scene_buffer *)node;
|
return (struct wlr_scene_raster *)node;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_scene *scene_node_get_root(struct wlr_scene_node *node) {
|
struct wlr_scene *scene_node_get_root(struct wlr_scene_node *node) {
|
||||||
|
|
@ -87,22 +87,21 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) {
|
||||||
wlr_signal_emit_safe(&node->events.destroy, NULL);
|
wlr_signal_emit_safe(&node->events.destroy, NULL);
|
||||||
|
|
||||||
struct wlr_scene *scene = scene_node_get_root(node);
|
struct wlr_scene *scene = scene_node_get_root(node);
|
||||||
if (node->type == WLR_SCENE_NODE_BUFFER) {
|
if (node->type == WLR_SCENE_NODE_RASTER) {
|
||||||
struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node);
|
struct wlr_scene_raster *scene_raster = wlr_scene_raster_from_node(node);
|
||||||
|
|
||||||
uint64_t active = scene_buffer->active_outputs;
|
uint64_t active = scene_raster->active_outputs;
|
||||||
if (active) {
|
if (active) {
|
||||||
struct wlr_scene_output *scene_output;
|
struct wlr_scene_output *scene_output;
|
||||||
wl_list_for_each(scene_output, &scene->outputs, link) {
|
wl_list_for_each(scene_output, &scene->outputs, link) {
|
||||||
if (active & (1ull << scene_output->index)) {
|
if (active & (1ull << scene_output->index)) {
|
||||||
wlr_signal_emit_safe(&scene_buffer->events.output_leave,
|
wlr_signal_emit_safe(&scene_raster->events.output_leave,
|
||||||
scene_output);
|
scene_output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_texture_destroy(scene_buffer->texture);
|
wlr_raster_unlock(scene_raster->raster);
|
||||||
wlr_buffer_unlock(scene_buffer->buffer);
|
|
||||||
} else if (node->type == WLR_SCENE_NODE_TREE) {
|
} else if (node->type == WLR_SCENE_NODE_TREE) {
|
||||||
struct wlr_scene_tree *scene_tree = scene_tree_from_node(node);
|
struct wlr_scene_tree *scene_tree = scene_tree_from_node(node);
|
||||||
|
|
||||||
|
|
@ -196,16 +195,16 @@ struct wlr_scene_tree *wlr_scene_tree_create(struct wlr_scene_tree *parent) {
|
||||||
static void scene_node_get_size(struct wlr_scene_node *node, int *lx, int *ly);
|
static void scene_node_get_size(struct wlr_scene_node *node, int *lx, int *ly);
|
||||||
|
|
||||||
// This function must be called whenever the coordinates/dimensions of a scene
|
// This function must be called whenever the coordinates/dimensions of a scene
|
||||||
// buffer or scene output change. It is not necessary to call when a scene
|
// raster or scene output change. It is not necessary to call when a scene
|
||||||
// buffer's node is enabled/disabled or obscured by other nodes.
|
// raster's node is enabled/disabled or obscured by other nodes.
|
||||||
static void scene_buffer_update_outputs(struct wlr_scene_buffer *scene_buffer,
|
static void scene_raster_update_outputs(struct wlr_scene_raster *scene_raster,
|
||||||
int lx, int ly, struct wlr_scene *scene,
|
int lx, int ly, struct wlr_scene *scene,
|
||||||
struct wlr_scene_output *ignore) {
|
struct wlr_scene_output *ignore) {
|
||||||
struct wlr_box buffer_box = { .x = lx, .y = ly };
|
struct wlr_box raster_box = { .x = lx, .y = ly };
|
||||||
scene_node_get_size(&scene_buffer->node, &buffer_box.width, &buffer_box.height);
|
scene_node_get_size(&scene_raster->node, &raster_box.width, &raster_box.height);
|
||||||
|
|
||||||
int largest_overlap = 0;
|
int largest_overlap = 0;
|
||||||
scene_buffer->primary_output = NULL;
|
scene_raster->primary_output = NULL;
|
||||||
|
|
||||||
uint64_t active_outputs = 0;
|
uint64_t active_outputs = 0;
|
||||||
|
|
||||||
|
|
@ -229,21 +228,21 @@ static void scene_buffer_update_outputs(struct wlr_scene_buffer *scene_buffer,
|
||||||
&output_box.width, &output_box.height);
|
&output_box.width, &output_box.height);
|
||||||
|
|
||||||
struct wlr_box intersection;
|
struct wlr_box intersection;
|
||||||
bool intersects = wlr_box_intersection(&intersection, &buffer_box, &output_box);
|
bool intersects = wlr_box_intersection(&intersection, &raster_box, &output_box);
|
||||||
|
|
||||||
if (intersects) {
|
if (intersects) {
|
||||||
int overlap = intersection.width * intersection.height;
|
int overlap = intersection.width * intersection.height;
|
||||||
if (overlap > largest_overlap) {
|
if (overlap > largest_overlap) {
|
||||||
largest_overlap = overlap;
|
largest_overlap = overlap;
|
||||||
scene_buffer->primary_output = scene_output;
|
scene_raster->primary_output = scene_output;
|
||||||
}
|
}
|
||||||
|
|
||||||
active_outputs |= 1ull << scene_output->index;
|
active_outputs |= 1ull << scene_output->index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t old_active = scene_buffer->active_outputs;
|
uint64_t old_active = scene_raster->active_outputs;
|
||||||
scene_buffer->active_outputs = active_outputs;
|
scene_raster->active_outputs = active_outputs;
|
||||||
|
|
||||||
wl_list_for_each(scene_output, &scene->outputs, link) {
|
wl_list_for_each(scene_output, &scene->outputs, link) {
|
||||||
uint64_t mask = 1ull << scene_output->index;
|
uint64_t mask = 1ull << scene_output->index;
|
||||||
|
|
@ -251,9 +250,9 @@ static void scene_buffer_update_outputs(struct wlr_scene_buffer *scene_buffer,
|
||||||
bool intersects_before = old_active & mask;
|
bool intersects_before = old_active & mask;
|
||||||
|
|
||||||
if (intersects && !intersects_before) {
|
if (intersects && !intersects_before) {
|
||||||
wlr_signal_emit_safe(&scene_buffer->events.output_enter, scene_output);
|
wlr_signal_emit_safe(&scene_raster->events.output_enter, scene_output);
|
||||||
} else if (!intersects && intersects_before) {
|
} else if (!intersects && intersects_before) {
|
||||||
wlr_signal_emit_safe(&scene_buffer->events.output_leave, scene_output);
|
wlr_signal_emit_safe(&scene_raster->events.output_leave, scene_output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -261,10 +260,10 @@ static void scene_buffer_update_outputs(struct wlr_scene_buffer *scene_buffer,
|
||||||
static void _scene_node_update_outputs(struct wlr_scene_node *node,
|
static void _scene_node_update_outputs(struct wlr_scene_node *node,
|
||||||
int lx, int ly, struct wlr_scene *scene,
|
int lx, int ly, struct wlr_scene *scene,
|
||||||
struct wlr_scene_output *ignore) {
|
struct wlr_scene_output *ignore) {
|
||||||
if (node->type == WLR_SCENE_NODE_BUFFER) {
|
if (node->type == WLR_SCENE_NODE_RASTER) {
|
||||||
struct wlr_scene_buffer *scene_buffer =
|
struct wlr_scene_raster *scene_raster =
|
||||||
wlr_scene_buffer_from_node(node);
|
wlr_scene_raster_from_node(node);
|
||||||
scene_buffer_update_outputs(scene_buffer, lx, ly, scene, ignore);
|
scene_raster_update_outputs(scene_raster, lx, ly, scene, ignore);
|
||||||
} else if (node->type == WLR_SCENE_NODE_TREE) {
|
} else if (node->type == WLR_SCENE_NODE_TREE) {
|
||||||
struct wlr_scene_tree *scene_tree = scene_tree_from_node(node);
|
struct wlr_scene_tree *scene_tree = scene_tree_from_node(node);
|
||||||
struct wlr_scene_node *child;
|
struct wlr_scene_node *child;
|
||||||
|
|
@ -322,57 +321,54 @@ void wlr_scene_rect_set_color(struct wlr_scene_rect *rect, const float color[sta
|
||||||
scene_node_damage_whole(&rect->node);
|
scene_node_damage_whole(&rect->node);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent,
|
struct wlr_scene_raster *wlr_scene_raster_create(struct wlr_scene_tree *parent,
|
||||||
struct wlr_buffer *buffer) {
|
struct wlr_raster *raster) {
|
||||||
struct wlr_scene_buffer *scene_buffer = calloc(1, sizeof(*scene_buffer));
|
struct wlr_scene_raster *scene_raster = calloc(1, sizeof(*scene_raster));
|
||||||
if (scene_buffer == NULL) {
|
if (scene_raster == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
assert(parent);
|
assert(parent);
|
||||||
scene_node_init(&scene_buffer->node, WLR_SCENE_NODE_BUFFER, parent);
|
scene_node_init(&scene_raster->node, WLR_SCENE_NODE_RASTER, parent);
|
||||||
|
|
||||||
if (buffer) {
|
if (raster) {
|
||||||
scene_buffer->buffer = wlr_buffer_lock(buffer);
|
scene_raster->raster = wlr_raster_lock(raster);
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_signal_init(&scene_buffer->events.output_enter);
|
wl_signal_init(&scene_raster->events.output_enter);
|
||||||
wl_signal_init(&scene_buffer->events.output_leave);
|
wl_signal_init(&scene_raster->events.output_leave);
|
||||||
wl_signal_init(&scene_buffer->events.output_present);
|
wl_signal_init(&scene_raster->events.output_present);
|
||||||
wl_signal_init(&scene_buffer->events.frame_done);
|
wl_signal_init(&scene_raster->events.frame_done);
|
||||||
|
|
||||||
scene_node_damage_whole(&scene_buffer->node);
|
scene_node_damage_whole(&scene_raster->node);
|
||||||
|
|
||||||
scene_node_update_outputs(&scene_buffer->node, NULL);
|
scene_node_update_outputs(&scene_raster->node, NULL);
|
||||||
|
|
||||||
return scene_buffer;
|
return scene_raster;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buffer,
|
void wlr_scene_raster_set_raster_with_damage(struct wlr_scene_raster *scene_raster,
|
||||||
struct wlr_buffer *buffer, pixman_region32_t *damage) {
|
struct wlr_raster *raster, pixman_region32_t *damage) {
|
||||||
// specifying a region for a NULL buffer doesn't make sense. We need to know
|
// specifying a region for a NULL raster doesn't make sense. We need to know
|
||||||
// about the buffer to scale the buffer local coordinates down to scene
|
// about the raster to scale the raster local coordinates down to scene
|
||||||
// coordinates.
|
// coordinates.
|
||||||
assert(buffer || !damage);
|
assert(raster || !damage);
|
||||||
|
|
||||||
if (buffer != scene_buffer->buffer) {
|
if (raster != scene_raster->raster) {
|
||||||
if (!damage) {
|
if (!damage) {
|
||||||
scene_node_damage_whole(&scene_buffer->node);
|
scene_node_damage_whole(&scene_raster->node);
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_texture_destroy(scene_buffer->texture);
|
wlr_raster_unlock(scene_raster->raster);
|
||||||
scene_buffer->texture = NULL;
|
scene_raster->raster = NULL;
|
||||||
wlr_buffer_unlock(scene_buffer->buffer);
|
|
||||||
|
|
||||||
if (buffer) {
|
if (raster) {
|
||||||
scene_buffer->buffer = wlr_buffer_lock(buffer);
|
scene_raster->raster = wlr_raster_lock(raster);
|
||||||
} else {
|
|
||||||
scene_buffer->buffer = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scene_node_update_outputs(&scene_buffer->node, NULL);
|
scene_node_update_outputs(&scene_raster->node, NULL);
|
||||||
|
|
||||||
if (!damage) {
|
if (!damage) {
|
||||||
scene_node_damage_whole(&scene_buffer->node);
|
scene_node_damage_whole(&scene_raster->node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -381,41 +377,41 @@ void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buff
|
||||||
}
|
}
|
||||||
|
|
||||||
int lx, ly;
|
int lx, ly;
|
||||||
if (!wlr_scene_node_coords(&scene_buffer->node, &lx, &ly)) {
|
if (!wlr_scene_node_coords(&scene_raster->node, &lx, &ly)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_fbox box = scene_buffer->src_box;
|
struct wlr_fbox box = scene_raster->src_box;
|
||||||
if (wlr_fbox_empty(&box)) {
|
if (wlr_fbox_empty(&box)) {
|
||||||
box.x = 0;
|
box.x = 0;
|
||||||
box.y = 0;
|
box.y = 0;
|
||||||
|
|
||||||
if (scene_buffer->transform & WL_OUTPUT_TRANSFORM_90) {
|
if (scene_raster->transform & WL_OUTPUT_TRANSFORM_90) {
|
||||||
box.width = buffer->height;
|
box.width = raster->height;
|
||||||
box.height = buffer->width;
|
box.height = raster->width;
|
||||||
} else {
|
} else {
|
||||||
box.width = buffer->width;
|
box.width = raster->width;
|
||||||
box.height = buffer->height;
|
box.height = raster->height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double scale_x, scale_y;
|
double scale_x, scale_y;
|
||||||
if (scene_buffer->dst_width || scene_buffer->dst_height) {
|
if (scene_raster->dst_width || scene_raster->dst_height) {
|
||||||
scale_x = scene_buffer->dst_width / box.width;
|
scale_x = scene_raster->dst_width / box.width;
|
||||||
scale_y = scene_buffer->dst_height / box.height;
|
scale_y = scene_raster->dst_height / box.height;
|
||||||
} else {
|
} else {
|
||||||
scale_x = buffer->width / box.width;
|
scale_x = raster->width / box.width;
|
||||||
scale_y = buffer->height / box.height;
|
scale_y = raster->height / box.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
pixman_region32_t trans_damage;
|
pixman_region32_t trans_damage;
|
||||||
pixman_region32_init(&trans_damage);
|
pixman_region32_init(&trans_damage);
|
||||||
wlr_region_transform(&trans_damage, damage,
|
wlr_region_transform(&trans_damage, damage,
|
||||||
scene_buffer->transform, buffer->width, buffer->height);
|
scene_raster->transform, raster->width, raster->height);
|
||||||
pixman_region32_intersect_rect(&trans_damage, &trans_damage,
|
pixman_region32_intersect_rect(&trans_damage, &trans_damage,
|
||||||
box.x, box.y, box.width, box.height);
|
box.x, box.y, box.width, box.height);
|
||||||
|
|
||||||
struct wlr_scene *scene = scene_node_get_root(&scene_buffer->node);
|
struct wlr_scene *scene = scene_node_get_root(&scene_raster->node);
|
||||||
struct wlr_scene_output *scene_output;
|
struct wlr_scene_output *scene_output;
|
||||||
wl_list_for_each(scene_output, &scene->outputs, link) {
|
wl_list_for_each(scene_output, &scene->outputs, link) {
|
||||||
float output_scale = scene_output->output->scale;
|
float output_scale = scene_output->output->scale;
|
||||||
|
|
@ -435,14 +431,14 @@ void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buff
|
||||||
pixman_region32_fini(&trans_damage);
|
pixman_region32_fini(&trans_damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_scene_buffer_set_buffer(struct wlr_scene_buffer *scene_buffer,
|
void wlr_scene_raster_set_raster(struct wlr_scene_raster *scene_raster,
|
||||||
struct wlr_buffer *buffer) {
|
struct wlr_raster *raster) {
|
||||||
wlr_scene_buffer_set_buffer_with_damage(scene_buffer, buffer, NULL);
|
wlr_scene_raster_set_raster_with_damage(scene_raster, raster, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_scene_buffer_set_source_box(struct wlr_scene_buffer *scene_buffer,
|
void wlr_scene_raster_set_source_box(struct wlr_scene_raster *scene_raster,
|
||||||
const struct wlr_fbox *box) {
|
const struct wlr_fbox *box) {
|
||||||
struct wlr_fbox *cur = &scene_buffer->src_box;
|
struct wlr_fbox *cur = &scene_raster->src_box;
|
||||||
if ((wlr_fbox_empty(box) && wlr_fbox_empty(cur)) ||
|
if ((wlr_fbox_empty(box) && wlr_fbox_empty(cur)) ||
|
||||||
(box != NULL && memcmp(cur, box, sizeof(*box)) == 0)) {
|
(box != NULL && memcmp(cur, box, sizeof(*box)) == 0)) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -454,56 +450,39 @@ void wlr_scene_buffer_set_source_box(struct wlr_scene_buffer *scene_buffer,
|
||||||
memset(cur, 0, sizeof(*cur));
|
memset(cur, 0, sizeof(*cur));
|
||||||
}
|
}
|
||||||
|
|
||||||
scene_node_damage_whole(&scene_buffer->node);
|
scene_node_damage_whole(&scene_raster->node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_scene_buffer_set_dest_size(struct wlr_scene_buffer *scene_buffer,
|
void wlr_scene_raster_set_dest_size(struct wlr_scene_raster *scene_raster,
|
||||||
int width, int height) {
|
int width, int height) {
|
||||||
if (scene_buffer->dst_width == width && scene_buffer->dst_height == height) {
|
if (scene_raster->dst_width == width && scene_raster->dst_height == height) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
scene_node_damage_whole(&scene_buffer->node);
|
scene_node_damage_whole(&scene_raster->node);
|
||||||
scene_buffer->dst_width = width;
|
scene_raster->dst_width = width;
|
||||||
scene_buffer->dst_height = height;
|
scene_raster->dst_height = height;
|
||||||
scene_node_damage_whole(&scene_buffer->node);
|
scene_node_damage_whole(&scene_raster->node);
|
||||||
|
|
||||||
scene_node_update_outputs(&scene_buffer->node, NULL);
|
scene_node_update_outputs(&scene_raster->node, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_scene_buffer_set_transform(struct wlr_scene_buffer *scene_buffer,
|
void wlr_scene_raster_set_transform(struct wlr_scene_raster *scene_raster,
|
||||||
enum wl_output_transform transform) {
|
enum wl_output_transform transform) {
|
||||||
if (scene_buffer->transform == transform) {
|
if (scene_raster->transform == transform) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
scene_node_damage_whole(&scene_buffer->node);
|
scene_node_damage_whole(&scene_raster->node);
|
||||||
scene_buffer->transform = transform;
|
scene_raster->transform = transform;
|
||||||
scene_node_damage_whole(&scene_buffer->node);
|
scene_node_damage_whole(&scene_raster->node);
|
||||||
|
|
||||||
scene_node_update_outputs(&scene_buffer->node, NULL);
|
scene_node_update_outputs(&scene_raster->node, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_scene_buffer_send_frame_done(struct wlr_scene_buffer *scene_buffer,
|
void wlr_scene_raster_send_frame_done(struct wlr_scene_raster *scene_raster,
|
||||||
struct timespec *now) {
|
struct timespec *now) {
|
||||||
wlr_signal_emit_safe(&scene_buffer->events.frame_done, now);
|
wlr_signal_emit_safe(&scene_raster->events.frame_done, now);
|
||||||
}
|
|
||||||
|
|
||||||
static struct wlr_texture *scene_buffer_get_texture(
|
|
||||||
struct wlr_scene_buffer *scene_buffer, struct wlr_renderer *renderer) {
|
|
||||||
struct wlr_client_buffer *client_buffer =
|
|
||||||
wlr_client_buffer_get(scene_buffer->buffer);
|
|
||||||
if (client_buffer != NULL) {
|
|
||||||
return client_buffer->texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scene_buffer->texture != NULL) {
|
|
||||||
return scene_buffer->texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
scene_buffer->texture =
|
|
||||||
wlr_texture_from_buffer(renderer, scene_buffer->buffer);
|
|
||||||
return scene_buffer->texture;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scene_node_get_size(struct wlr_scene_node *node,
|
static void scene_node_get_size(struct wlr_scene_node *node,
|
||||||
|
|
@ -519,18 +498,18 @@ static void scene_node_get_size(struct wlr_scene_node *node,
|
||||||
*width = scene_rect->width;
|
*width = scene_rect->width;
|
||||||
*height = scene_rect->height;
|
*height = scene_rect->height;
|
||||||
break;
|
break;
|
||||||
case WLR_SCENE_NODE_BUFFER:;
|
case WLR_SCENE_NODE_RASTER:;
|
||||||
struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node);
|
struct wlr_scene_raster *scene_raster = wlr_scene_raster_from_node(node);
|
||||||
if (scene_buffer->dst_width > 0 && scene_buffer->dst_height > 0) {
|
if (scene_raster->dst_width > 0 && scene_raster->dst_height > 0) {
|
||||||
*width = scene_buffer->dst_width;
|
*width = scene_raster->dst_width;
|
||||||
*height = scene_buffer->dst_height;
|
*height = scene_raster->dst_height;
|
||||||
} else if (scene_buffer->buffer) {
|
} else if (scene_raster->raster) {
|
||||||
if (scene_buffer->transform & WL_OUTPUT_TRANSFORM_90) {
|
if (scene_raster->transform & WL_OUTPUT_TRANSFORM_90) {
|
||||||
*height = scene_buffer->buffer->width;
|
*height = scene_raster->raster->width;
|
||||||
*width = scene_buffer->buffer->height;
|
*width = scene_raster->raster->height;
|
||||||
} else {
|
} else {
|
||||||
*width = scene_buffer->buffer->width;
|
*width = scene_raster->raster->width;
|
||||||
*height = scene_buffer->buffer->height;
|
*height = scene_raster->raster->height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -718,8 +697,8 @@ bool wlr_scene_node_coords(struct wlr_scene_node *node,
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scene_node_for_each_scene_buffer(struct wlr_scene_node *node,
|
static void scene_node_for_each_scene_raster(struct wlr_scene_node *node,
|
||||||
int lx, int ly, wlr_scene_buffer_iterator_func_t user_iterator,
|
int lx, int ly, wlr_scene_raster_iterator_func_t user_iterator,
|
||||||
void *user_data) {
|
void *user_data) {
|
||||||
if (!node->enabled) {
|
if (!node->enabled) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -728,21 +707,21 @@ static void scene_node_for_each_scene_buffer(struct wlr_scene_node *node,
|
||||||
lx += node->x;
|
lx += node->x;
|
||||||
ly += node->y;
|
ly += node->y;
|
||||||
|
|
||||||
if (node->type == WLR_SCENE_NODE_BUFFER) {
|
if (node->type == WLR_SCENE_NODE_RASTER) {
|
||||||
struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node);
|
struct wlr_scene_raster *scene_raster = wlr_scene_raster_from_node(node);
|
||||||
user_iterator(scene_buffer, lx, ly, user_data);
|
user_iterator(scene_raster, lx, ly, user_data);
|
||||||
} else if (node->type == WLR_SCENE_NODE_TREE) {
|
} else if (node->type == WLR_SCENE_NODE_TREE) {
|
||||||
struct wlr_scene_tree *scene_tree = scene_tree_from_node(node);
|
struct wlr_scene_tree *scene_tree = scene_tree_from_node(node);
|
||||||
struct wlr_scene_node *child;
|
struct wlr_scene_node *child;
|
||||||
wl_list_for_each(child, &scene_tree->children, link) {
|
wl_list_for_each(child, &scene_tree->children, link) {
|
||||||
scene_node_for_each_scene_buffer(child, lx, ly, user_iterator, user_data);
|
scene_node_for_each_scene_raster(child, lx, ly, user_iterator, user_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_scene_node_for_each_buffer(struct wlr_scene_node *node,
|
void wlr_scene_node_for_each_raster(struct wlr_scene_node *node,
|
||||||
wlr_scene_buffer_iterator_func_t user_iterator, void *user_data) {
|
wlr_scene_raster_iterator_func_t user_iterator, void *user_data) {
|
||||||
scene_node_for_each_scene_buffer(node, 0, 0, user_iterator, user_data);
|
scene_node_for_each_scene_raster(node, 0, 0, user_iterator, user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_scene_node *wlr_scene_node_at(struct wlr_scene_node *node,
|
struct wlr_scene_node *wlr_scene_node_at(struct wlr_scene_node *node,
|
||||||
|
|
@ -773,11 +752,11 @@ struct wlr_scene_node *wlr_scene_node_at(struct wlr_scene_node *node,
|
||||||
scene_node_get_size(node, &width, &height);
|
scene_node_get_size(node, &width, &height);
|
||||||
intersects = lx >= 0 && lx < width && ly >= 0 && ly < height;
|
intersects = lx >= 0 && lx < width && ly >= 0 && ly < height;
|
||||||
break;
|
break;
|
||||||
case WLR_SCENE_NODE_BUFFER:;
|
case WLR_SCENE_NODE_RASTER:;
|
||||||
struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node);
|
struct wlr_scene_raster *scene_raster = wlr_scene_raster_from_node(node);
|
||||||
|
|
||||||
if (scene_buffer->point_accepts_input) {
|
if (scene_raster->point_accepts_input) {
|
||||||
intersects = scene_buffer->point_accepts_input(scene_buffer, lx, ly);
|
intersects = scene_raster->point_accepts_input(scene_raster, lx, ly);
|
||||||
} else {
|
} else {
|
||||||
int width, height;
|
int width, height;
|
||||||
scene_node_get_size(node, &width, &height);
|
scene_node_get_size(node, &width, &height);
|
||||||
|
|
@ -841,8 +820,8 @@ static void render_rect(struct wlr_output *output,
|
||||||
pixman_region32_fini(&damage);
|
pixman_region32_fini(&damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void render_texture(struct wlr_output *output,
|
static void render_raster(struct wlr_output *output,
|
||||||
pixman_region32_t *output_damage, struct wlr_texture *texture,
|
pixman_region32_t *output_damage, struct wlr_raster *raster,
|
||||||
const struct wlr_fbox *src_box, const struct wlr_box *dst_box,
|
const struct wlr_fbox *src_box, const struct wlr_box *dst_box,
|
||||||
const float matrix[static 9]) {
|
const float matrix[static 9]) {
|
||||||
struct wlr_renderer *renderer = output->renderer;
|
struct wlr_renderer *renderer = output->renderer;
|
||||||
|
|
@ -850,8 +829,8 @@ static void render_texture(struct wlr_output *output,
|
||||||
|
|
||||||
struct wlr_fbox default_src_box = {0};
|
struct wlr_fbox default_src_box = {0};
|
||||||
if (wlr_fbox_empty(src_box)) {
|
if (wlr_fbox_empty(src_box)) {
|
||||||
default_src_box.width = texture->width;
|
default_src_box.width = raster->width;
|
||||||
default_src_box.height = texture->height;
|
default_src_box.height = raster->height;
|
||||||
src_box = &default_src_box;
|
src_box = &default_src_box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -865,7 +844,7 @@ static void render_texture(struct wlr_output *output,
|
||||||
pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
|
pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
|
||||||
for (int i = 0; i < nrects; ++i) {
|
for (int i = 0; i < nrects; ++i) {
|
||||||
scissor_output(output, &rects[i]);
|
scissor_output(output, &rects[i]);
|
||||||
wlr_render_subtexture_with_matrix(renderer, texture, src_box, matrix, 1.0);
|
wlr_render_subraster_with_matrix(renderer, raster, src_box, matrix, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pixman_region32_fini(&damage);
|
pixman_region32_fini(&damage);
|
||||||
|
|
@ -890,7 +869,6 @@ static void render_node_iterator(struct wlr_scene_node *node,
|
||||||
scene_node_get_size(node, &dst_box.width, &dst_box.height);
|
scene_node_get_size(node, &dst_box.width, &dst_box.height);
|
||||||
scale_box(&dst_box, output->scale);
|
scale_box(&dst_box, output->scale);
|
||||||
|
|
||||||
struct wlr_texture *texture;
|
|
||||||
float matrix[9];
|
float matrix[9];
|
||||||
enum wl_output_transform transform;
|
enum wl_output_transform transform;
|
||||||
switch (node->type) {
|
switch (node->type) {
|
||||||
|
|
@ -903,26 +881,20 @@ static void render_node_iterator(struct wlr_scene_node *node,
|
||||||
render_rect(output, output_damage, scene_rect->color, &dst_box,
|
render_rect(output, output_damage, scene_rect->color, &dst_box,
|
||||||
output->transform_matrix);
|
output->transform_matrix);
|
||||||
break;
|
break;
|
||||||
case WLR_SCENE_NODE_BUFFER:;
|
case WLR_SCENE_NODE_RASTER:;
|
||||||
struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node);
|
struct wlr_scene_raster *scene_raster = wlr_scene_raster_from_node(node);
|
||||||
if (!scene_buffer->buffer) {
|
if (!scene_raster->raster) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_renderer *renderer = output->renderer;
|
transform = wlr_output_transform_invert(scene_raster->transform);
|
||||||
texture = scene_buffer_get_texture(scene_buffer, renderer);
|
|
||||||
if (texture == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
transform = wlr_output_transform_invert(scene_buffer->transform);
|
|
||||||
wlr_matrix_project_box(matrix, &dst_box, transform, 0.0,
|
wlr_matrix_project_box(matrix, &dst_box, transform, 0.0,
|
||||||
output->transform_matrix);
|
output->transform_matrix);
|
||||||
|
|
||||||
render_texture(output, output_damage, texture, &scene_buffer->src_box,
|
render_raster(output, output_damage, scene_raster->raster,
|
||||||
&dst_box, matrix);
|
&scene_raster->src_box, &dst_box, matrix);
|
||||||
|
|
||||||
wlr_signal_emit_safe(&scene_buffer->events.output_present, scene_output);
|
wlr_signal_emit_safe(&scene_raster->events.output_present, scene_output);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1181,31 +1153,35 @@ static bool scene_output_scanout(struct wlr_scene_output *scene_output) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_scene_node *node = check_scanout_data.node;
|
struct wlr_scene_node *node = check_scanout_data.node;
|
||||||
struct wlr_buffer *buffer;
|
struct wlr_raster *raster;
|
||||||
switch (node->type) {
|
switch (node->type) {
|
||||||
case WLR_SCENE_NODE_BUFFER:;
|
case WLR_SCENE_NODE_RASTER:;
|
||||||
struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node);
|
struct wlr_scene_raster *scene_raster = wlr_scene_raster_from_node(node);
|
||||||
if (scene_buffer->buffer == NULL ||
|
if (scene_raster->raster == NULL ||
|
||||||
!wlr_fbox_empty(&scene_buffer->src_box) ||
|
!wlr_fbox_empty(&scene_raster->src_box) ||
|
||||||
scene_buffer->transform != output->transform) {
|
scene_raster->transform != output->transform) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
buffer = scene_buffer->buffer;
|
raster = scene_raster->raster;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_output_attach_buffer(output, buffer);
|
if (!raster->buffer) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_output_attach_buffer(output, raster->buffer);
|
||||||
if (!wlr_output_test(output)) {
|
if (!wlr_output_test(output)) {
|
||||||
wlr_output_rollback(output);
|
wlr_output_rollback(output);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->type == WLR_SCENE_NODE_BUFFER) {
|
if (node->type == WLR_SCENE_NODE_RASTER) {
|
||||||
struct wlr_scene_buffer *scene_buffer =
|
struct wlr_scene_raster *scene_raster =
|
||||||
wlr_scene_buffer_from_node(node);
|
wlr_scene_raster_from_node(node);
|
||||||
wlr_signal_emit_safe(&scene_buffer->events.output_present, scene_output);
|
wlr_signal_emit_safe(&scene_raster->events.output_present, scene_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
return wlr_output_commit(output);
|
return wlr_output_commit(output);
|
||||||
|
|
@ -1371,12 +1347,12 @@ static void scene_node_send_frame_done(struct wlr_scene_node *node,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->type == WLR_SCENE_NODE_BUFFER) {
|
if (node->type == WLR_SCENE_NODE_RASTER) {
|
||||||
struct wlr_scene_buffer *scene_buffer =
|
struct wlr_scene_raster *scene_raster =
|
||||||
wlr_scene_buffer_from_node(node);
|
wlr_scene_raster_from_node(node);
|
||||||
|
|
||||||
if (scene_buffer->primary_output == scene_output) {
|
if (scene_raster->primary_output == scene_output) {
|
||||||
wlr_scene_buffer_send_frame_done(scene_buffer, now);
|
wlr_scene_raster_send_frame_done(scene_raster, now);
|
||||||
}
|
}
|
||||||
} else if (node->type == WLR_SCENE_NODE_TREE) {
|
} else if (node->type == WLR_SCENE_NODE_TREE) {
|
||||||
struct wlr_scene_tree *scene_tree = scene_tree_from_node(node);
|
struct wlr_scene_tree *scene_tree = scene_tree_from_node(node);
|
||||||
|
|
@ -1393,9 +1369,9 @@ void wlr_scene_output_send_frame_done(struct wlr_scene_output *scene_output,
|
||||||
scene_output, now);
|
scene_output, now);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scene_output_for_each_scene_buffer(const struct wlr_box *output_box,
|
static void scene_output_for_each_scene_raster(const struct wlr_box *output_box,
|
||||||
struct wlr_scene_node *node, int lx, int ly,
|
struct wlr_scene_node *node, int lx, int ly,
|
||||||
wlr_scene_buffer_iterator_func_t user_iterator, void *user_data) {
|
wlr_scene_raster_iterator_func_t user_iterator, void *user_data) {
|
||||||
if (!node->enabled) {
|
if (!node->enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1403,31 +1379,31 @@ static void scene_output_for_each_scene_buffer(const struct wlr_box *output_box,
|
||||||
lx += node->x;
|
lx += node->x;
|
||||||
ly += node->y;
|
ly += node->y;
|
||||||
|
|
||||||
if (node->type == WLR_SCENE_NODE_BUFFER) {
|
if (node->type == WLR_SCENE_NODE_RASTER) {
|
||||||
struct wlr_box node_box = { .x = lx, .y = ly };
|
struct wlr_box node_box = { .x = lx, .y = ly };
|
||||||
scene_node_get_size(node, &node_box.width, &node_box.height);
|
scene_node_get_size(node, &node_box.width, &node_box.height);
|
||||||
|
|
||||||
struct wlr_box intersection;
|
struct wlr_box intersection;
|
||||||
if (wlr_box_intersection(&intersection, output_box, &node_box)) {
|
if (wlr_box_intersection(&intersection, output_box, &node_box)) {
|
||||||
struct wlr_scene_buffer *scene_buffer =
|
struct wlr_scene_raster *scene_raster =
|
||||||
wlr_scene_buffer_from_node(node);
|
wlr_scene_raster_from_node(node);
|
||||||
user_iterator(scene_buffer, lx, ly, user_data);
|
user_iterator(scene_raster, lx, ly, user_data);
|
||||||
}
|
}
|
||||||
} else if (node->type == WLR_SCENE_NODE_TREE) {
|
} else if (node->type == WLR_SCENE_NODE_TREE) {
|
||||||
struct wlr_scene_tree *scene_tree = scene_tree_from_node(node);
|
struct wlr_scene_tree *scene_tree = scene_tree_from_node(node);
|
||||||
struct wlr_scene_node *child;
|
struct wlr_scene_node *child;
|
||||||
wl_list_for_each(child, &scene_tree->children, link) {
|
wl_list_for_each(child, &scene_tree->children, link) {
|
||||||
scene_output_for_each_scene_buffer(output_box, child, lx, ly,
|
scene_output_for_each_scene_raster(output_box, child, lx, ly,
|
||||||
user_iterator, user_data);
|
user_iterator, user_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_scene_output_for_each_buffer(struct wlr_scene_output *scene_output,
|
void wlr_scene_output_for_each_raster(struct wlr_scene_output *scene_output,
|
||||||
wlr_scene_buffer_iterator_func_t iterator, void *user_data) {
|
wlr_scene_raster_iterator_func_t iterator, void *user_data) {
|
||||||
struct wlr_box box = { .x = scene_output->x, .y = scene_output->y };
|
struct wlr_box box = { .x = scene_output->x, .y = scene_output->y };
|
||||||
wlr_output_effective_resolution(scene_output->output,
|
wlr_output_effective_resolution(scene_output->output,
|
||||||
&box.width, &box.height);
|
&box.width, &box.height);
|
||||||
scene_output_for_each_scene_buffer(&box, &scene_output->scene->tree.node, 0, 0,
|
scene_output_for_each_scene_raster(&box, &scene_output->scene->tree.node, 0, 0,
|
||||||
iterator, user_data);
|
iterator, user_data);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -109,59 +109,8 @@ bool wlr_resource_is_buffer(struct wl_resource *resource) {
|
||||||
return strcmp(wl_resource_get_class(resource), wl_buffer_interface.name) == 0;
|
return strcmp(wl_resource_get_class(resource), wl_buffer_interface.name) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wlr_buffer_impl client_buffer_impl;
|
|
||||||
|
|
||||||
struct wlr_client_buffer *wlr_client_buffer_get(struct wlr_buffer *buffer) {
|
|
||||||
if (buffer->impl != &client_buffer_impl) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return (struct wlr_client_buffer *)buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct wlr_client_buffer *client_buffer_from_buffer(
|
|
||||||
struct wlr_buffer *buffer) {
|
|
||||||
struct wlr_client_buffer *client_buffer = wlr_client_buffer_get(buffer);
|
|
||||||
assert(client_buffer != NULL);
|
|
||||||
return client_buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void client_buffer_destroy(struct wlr_buffer *buffer) {
|
|
||||||
struct wlr_client_buffer *client_buffer = client_buffer_from_buffer(buffer);
|
|
||||||
wl_list_remove(&client_buffer->source_destroy.link);
|
|
||||||
wlr_texture_destroy(client_buffer->texture);
|
|
||||||
free(client_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool client_buffer_get_dmabuf(struct wlr_buffer *buffer,
|
|
||||||
struct wlr_dmabuf_attributes *attribs) {
|
|
||||||
struct wlr_client_buffer *client_buffer = client_buffer_from_buffer(buffer);
|
|
||||||
|
|
||||||
if (client_buffer->source == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return wlr_buffer_get_dmabuf(client_buffer->source, attribs);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wlr_buffer_impl client_buffer_impl = {
|
|
||||||
.destroy = client_buffer_destroy,
|
|
||||||
.get_dmabuf = client_buffer_get_dmabuf,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void client_buffer_handle_source_destroy(struct wl_listener *listener,
|
|
||||||
void *data) {
|
|
||||||
struct wlr_client_buffer *client_buffer =
|
|
||||||
wl_container_of(listener, client_buffer, source_destroy);
|
|
||||||
wl_list_remove(&client_buffer->source_destroy.link);
|
|
||||||
wl_list_init(&client_buffer->source_destroy.link);
|
|
||||||
client_buffer->source = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct wlr_shm_client_buffer *shm_client_buffer_get_or_create(
|
static struct wlr_shm_client_buffer *shm_client_buffer_get_or_create(
|
||||||
struct wl_resource *resource);
|
struct wl_resource *resource);
|
||||||
static bool buffer_is_shm_client_buffer(struct wlr_buffer *buffer);
|
|
||||||
static struct wlr_shm_client_buffer *shm_client_buffer_from_buffer(
|
|
||||||
struct wlr_buffer *buffer);
|
|
||||||
|
|
||||||
/* struct wlr_buffer_resource_interface */
|
/* struct wlr_buffer_resource_interface */
|
||||||
static struct wl_array buffer_resource_interfaces = {0};
|
static struct wl_array buffer_resource_interfaces = {0};
|
||||||
|
|
@ -263,99 +212,13 @@ bool buffer_is_opaque(struct wlr_buffer *buffer) {
|
||||||
return !format_info->has_alpha;
|
return !format_info->has_alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_client_buffer *wlr_client_buffer_create(struct wlr_buffer *buffer,
|
|
||||||
struct wlr_renderer *renderer) {
|
|
||||||
struct wlr_texture *texture = wlr_texture_from_buffer(renderer, buffer);
|
|
||||||
if (texture == NULL) {
|
|
||||||
wlr_log(WLR_ERROR, "Failed to create texture");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_client_buffer *client_buffer =
|
|
||||||
calloc(1, sizeof(struct wlr_client_buffer));
|
|
||||||
if (client_buffer == NULL) {
|
|
||||||
wlr_texture_destroy(texture);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
wlr_buffer_init(&client_buffer->base, &client_buffer_impl,
|
|
||||||
texture->width, texture->height);
|
|
||||||
client_buffer->source = buffer;
|
|
||||||
client_buffer->texture = texture;
|
|
||||||
|
|
||||||
wl_signal_add(&buffer->events.destroy, &client_buffer->source_destroy);
|
|
||||||
client_buffer->source_destroy.notify = client_buffer_handle_source_destroy;
|
|
||||||
|
|
||||||
if (buffer_is_shm_client_buffer(buffer)) {
|
|
||||||
struct wlr_shm_client_buffer *shm_client_buffer =
|
|
||||||
shm_client_buffer_from_buffer(buffer);
|
|
||||||
client_buffer->shm_source_format = shm_client_buffer->format;
|
|
||||||
} else {
|
|
||||||
client_buffer->shm_source_format = DRM_FORMAT_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure the buffer will be released before being destroyed
|
|
||||||
wlr_buffer_lock(&client_buffer->base);
|
|
||||||
wlr_buffer_drop(&client_buffer->base);
|
|
||||||
|
|
||||||
return client_buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool wlr_client_buffer_apply_damage(struct wlr_client_buffer *client_buffer,
|
|
||||||
struct wlr_buffer *next, pixman_region32_t *damage) {
|
|
||||||
if (client_buffer->base.n_locks > 1) {
|
|
||||||
// Someone else still has a reference to the buffer
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((uint32_t)next->width != client_buffer->texture->width ||
|
|
||||||
(uint32_t)next->height != client_buffer->texture->height) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (client_buffer->shm_source_format == DRM_FORMAT_INVALID) {
|
|
||||||
// Uploading only damaged regions only works for wl_shm buffers and
|
|
||||||
// mutable textures (created from wl_shm buffer)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *data;
|
|
||||||
uint32_t format;
|
|
||||||
size_t stride;
|
|
||||||
if (!wlr_buffer_begin_data_ptr_access(next, WLR_BUFFER_DATA_PTR_ACCESS_READ,
|
|
||||||
&data, &format, &stride)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (format != client_buffer->shm_source_format) {
|
|
||||||
// Uploading to textures can't change the format
|
|
||||||
wlr_buffer_end_data_ptr_access(next);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int n;
|
|
||||||
pixman_box32_t *rects = pixman_region32_rectangles(damage, &n);
|
|
||||||
for (int i = 0; i < n; ++i) {
|
|
||||||
pixman_box32_t *r = &rects[i];
|
|
||||||
if (!wlr_texture_write_pixels(client_buffer->texture, stride,
|
|
||||||
r->x2 - r->x1, r->y2 - r->y1, r->x1, r->y1,
|
|
||||||
r->x1, r->y1, data)) {
|
|
||||||
wlr_buffer_end_data_ptr_access(next);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wlr_buffer_end_data_ptr_access(next);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wlr_buffer_impl shm_client_buffer_impl;
|
static const struct wlr_buffer_impl shm_client_buffer_impl;
|
||||||
|
|
||||||
static bool buffer_is_shm_client_buffer(struct wlr_buffer *buffer) {
|
bool buffer_is_shm_client_buffer(struct wlr_buffer *buffer) {
|
||||||
return buffer->impl == &shm_client_buffer_impl;
|
return buffer->impl == &shm_client_buffer_impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_shm_client_buffer *shm_client_buffer_from_buffer(
|
struct wlr_shm_client_buffer *shm_client_buffer_from_buffer(
|
||||||
struct wlr_buffer *buffer) {
|
struct wlr_buffer *buffer) {
|
||||||
assert(buffer_is_shm_client_buffer(buffer));
|
assert(buffer_is_shm_client_buffer(buffer));
|
||||||
return (struct wlr_shm_client_buffer *)buffer;
|
return (struct wlr_shm_client_buffer *)buffer;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <wayland-server-core.h>
|
#include <wayland-server-core.h>
|
||||||
|
#include <wlr/interfaces/wlr_buffer.h>
|
||||||
#include <wlr/render/interface.h>
|
#include <wlr/render/interface.h>
|
||||||
#include <wlr/types/wlr_buffer.h>
|
#include <wlr/types/wlr_buffer.h>
|
||||||
#include <wlr/types/wlr_compositor.h>
|
#include <wlr/types/wlr_compositor.h>
|
||||||
|
|
@ -333,45 +334,15 @@ static void surface_state_move(struct wlr_surface_state *state,
|
||||||
static void surface_apply_damage(struct wlr_surface *surface) {
|
static void surface_apply_damage(struct wlr_surface *surface) {
|
||||||
if (surface->current.buffer == NULL) {
|
if (surface->current.buffer == NULL) {
|
||||||
// NULL commit
|
// NULL commit
|
||||||
if (surface->buffer != NULL) {
|
|
||||||
wlr_buffer_unlock(&surface->buffer->base);
|
|
||||||
}
|
|
||||||
surface->buffer = NULL;
|
|
||||||
surface->opaque = false;
|
surface->opaque = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
surface->opaque = buffer_is_opaque(surface->current.buffer);
|
surface->opaque = buffer_is_opaque(surface->current.buffer);
|
||||||
|
|
||||||
if (surface->buffer != NULL) {
|
|
||||||
if (wlr_client_buffer_apply_damage(surface->buffer,
|
|
||||||
surface->current.buffer, &surface->buffer_damage)) {
|
|
||||||
wlr_buffer_unlock(surface->current.buffer);
|
|
||||||
surface->current.buffer = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_client_buffer *buffer = wlr_client_buffer_create(
|
|
||||||
surface->current.buffer, surface->renderer);
|
|
||||||
|
|
||||||
wlr_buffer_unlock(surface->current.buffer);
|
|
||||||
surface->current.buffer = NULL;
|
|
||||||
|
|
||||||
if (buffer == NULL) {
|
|
||||||
wlr_log(WLR_ERROR, "Failed to upload buffer");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (surface->buffer != NULL) {
|
|
||||||
wlr_buffer_unlock(&surface->buffer->base);
|
|
||||||
}
|
|
||||||
surface->buffer = buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void surface_update_opaque_region(struct wlr_surface *surface) {
|
static void surface_update_opaque_region(struct wlr_surface *surface) {
|
||||||
struct wlr_texture *texture = wlr_surface_get_texture(surface);
|
if (!wlr_surface_has_buffer(surface)) {
|
||||||
if (texture == NULL) {
|
|
||||||
pixman_region32_clear(&surface->opaque_region);
|
pixman_region32_clear(&surface->opaque_region);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -445,8 +416,34 @@ static void surface_commit_state(struct wlr_surface *surface,
|
||||||
surface_state_move(&surface->current, next);
|
surface_state_move(&surface->current, next);
|
||||||
|
|
||||||
if (invalid_buffer) {
|
if (invalid_buffer) {
|
||||||
|
if (!surface->current.buffer) {
|
||||||
|
wlr_raster_unlock(surface->raster);
|
||||||
|
surface->raster = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!surface->raster || surface->raster->buffer != surface->current.buffer) {
|
||||||
|
surface->old_raster = surface->raster;
|
||||||
|
|
||||||
|
if (surface->current.buffer) {
|
||||||
|
surface->raster = wlr_raster_create(surface->current.buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (surface->old_raster) {
|
||||||
|
// By the time we unlock the buffer next the buffer might
|
||||||
|
// get destroyed. We need to start listening here.
|
||||||
|
wl_signal_add(&surface->old_raster->events.destroy,
|
||||||
|
&surface->raster_destroy);
|
||||||
|
|
||||||
|
wlr_raster_unlock(surface->old_raster);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
surface_apply_damage(surface);
|
surface_apply_damage(surface);
|
||||||
|
|
||||||
|
wlr_buffer_unlock(surface->current.buffer);
|
||||||
|
surface->current.buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
surface_update_opaque_region(surface);
|
surface_update_opaque_region(surface);
|
||||||
surface_update_input_region(surface);
|
surface_update_input_region(surface);
|
||||||
|
|
||||||
|
|
@ -480,6 +477,37 @@ static void surface_commit_state(struct wlr_surface *surface,
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_signal_emit_safe(&surface->events.commit, surface);
|
wlr_signal_emit_safe(&surface->events.commit, surface);
|
||||||
|
|
||||||
|
if (surface->old_raster) {
|
||||||
|
wl_list_remove(&surface->raster_destroy.link);
|
||||||
|
surface->old_raster = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invalid_buffer && surface->raster) {
|
||||||
|
// upload the texture to all renderers that this surface intersects.
|
||||||
|
struct wlr_surface_output *surface_output;
|
||||||
|
wl_list_for_each(surface_output, &surface->current_outputs, link) {
|
||||||
|
if (!surface_output->output->renderer) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_renderer_raster_upload(surface_output->output->renderer,
|
||||||
|
surface->raster);
|
||||||
|
}
|
||||||
|
|
||||||
|
// unlock the buffer for shm buffers only. Clients may implement
|
||||||
|
// optimizations if given the shm buffer back immediately. But only do
|
||||||
|
// this if the raster has a source, if not, that means that the surface
|
||||||
|
// is not visible on any outputs and let's continue locking the buffer
|
||||||
|
// until it is visible.
|
||||||
|
//
|
||||||
|
// For other buffers, we want to continue to lock it so that we
|
||||||
|
// may direct scanout.
|
||||||
|
if (!wl_list_empty(&surface->raster->sources) && surface->raster->buffer &&
|
||||||
|
buffer_is_shm_client_buffer(surface->raster->buffer)) {
|
||||||
|
wlr_raster_remove_buffer(surface->raster);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void collect_subsurface_damage_iter(struct wlr_surface *surface,
|
static void collect_subsurface_damage_iter(struct wlr_surface *surface,
|
||||||
|
|
@ -644,6 +672,8 @@ static void surface_handle_resource_destroy(struct wl_resource *resource) {
|
||||||
surface_output_destroy(surface_output);
|
surface_output_destroy(surface_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wlr_raster_unlock(surface->raster);
|
||||||
|
|
||||||
wlr_signal_emit_safe(&surface->events.destroy, surface);
|
wlr_signal_emit_safe(&surface->events.destroy, surface);
|
||||||
|
|
||||||
wlr_addon_set_finish(&surface->addons);
|
wlr_addon_set_finish(&surface->addons);
|
||||||
|
|
@ -653,28 +683,63 @@ static void surface_handle_resource_destroy(struct wl_resource *resource) {
|
||||||
surface_state_destroy_cached(cached);
|
surface_state_destroy_cached(cached);
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_list_remove(&surface->renderer_destroy.link);
|
|
||||||
surface_state_finish(&surface->pending);
|
surface_state_finish(&surface->pending);
|
||||||
surface_state_finish(&surface->current);
|
surface_state_finish(&surface->current);
|
||||||
pixman_region32_fini(&surface->buffer_damage);
|
pixman_region32_fini(&surface->buffer_damage);
|
||||||
pixman_region32_fini(&surface->external_damage);
|
pixman_region32_fini(&surface->external_damage);
|
||||||
pixman_region32_fini(&surface->opaque_region);
|
pixman_region32_fini(&surface->opaque_region);
|
||||||
pixman_region32_fini(&surface->input_region);
|
pixman_region32_fini(&surface->input_region);
|
||||||
if (surface->buffer != NULL) {
|
|
||||||
wlr_buffer_unlock(&surface->buffer->base);
|
|
||||||
}
|
|
||||||
free(surface);
|
free(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void surface_handle_renderer_destroy(struct wl_listener *listener,
|
static void surface_handle_raster_destroy(struct wl_listener *listener, void *data) {
|
||||||
void *data) {
|
|
||||||
struct wlr_surface *surface =
|
struct wlr_surface *surface =
|
||||||
wl_container_of(listener, surface, renderer_destroy);
|
wl_container_of(listener, surface, raster_destroy);
|
||||||
wl_resource_destroy(surface->resource);
|
|
||||||
|
// if there are already sources for the new raster, don't bother uploading
|
||||||
|
// if something else already did for us.
|
||||||
|
if (!wl_list_empty(&surface->raster->sources)) {
|
||||||
|
surface->old_raster = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to reclaim the textures from this raster so we can try to do a partial
|
||||||
|
// upload.
|
||||||
|
struct wlr_texture *texture, *tmp_texture;
|
||||||
|
wl_list_for_each_safe(texture, tmp_texture,
|
||||||
|
&surface->old_raster->sources, link) {
|
||||||
|
wlr_raster_detach(surface->old_raster, texture);
|
||||||
|
|
||||||
|
bool visible = false;
|
||||||
|
|
||||||
|
// only try to reuse textures of renderers that will see this surface.
|
||||||
|
struct wlr_surface_output *surface_output;
|
||||||
|
wl_list_for_each(surface_output, &surface->current_outputs, link) {
|
||||||
|
if (surface_output->output->renderer == texture->renderer) {
|
||||||
|
visible = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!visible) {
|
||||||
|
wlr_texture_destroy(texture);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wlr_texture_update_from_raster(texture,
|
||||||
|
surface->raster, &surface->buffer_damage)) {
|
||||||
|
wlr_texture_destroy(texture);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_raster_attach(surface->raster, texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
surface->old_raster = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_surface *surface_create(struct wl_client *client,
|
static struct wlr_surface *surface_create(struct wl_client *client,
|
||||||
uint32_t version, uint32_t id, struct wlr_renderer *renderer) {
|
uint32_t version, uint32_t id) {
|
||||||
struct wlr_surface *surface = calloc(1, sizeof(struct wlr_surface));
|
struct wlr_surface *surface = calloc(1, sizeof(struct wlr_surface));
|
||||||
if (!surface) {
|
if (!surface) {
|
||||||
wl_client_post_no_memory(client);
|
wl_client_post_no_memory(client);
|
||||||
|
|
@ -692,8 +757,6 @@ static struct wlr_surface *surface_create(struct wl_client *client,
|
||||||
|
|
||||||
wlr_log(WLR_DEBUG, "New wlr_surface %p (res %p)", surface, surface->resource);
|
wlr_log(WLR_DEBUG, "New wlr_surface %p (res %p)", surface, surface->resource);
|
||||||
|
|
||||||
surface->renderer = renderer;
|
|
||||||
|
|
||||||
surface_state_init(&surface->current);
|
surface_state_init(&surface->current);
|
||||||
surface_state_init(&surface->pending);
|
surface_state_init(&surface->pending);
|
||||||
surface->pending.seq = 1;
|
surface->pending.seq = 1;
|
||||||
|
|
@ -710,21 +773,13 @@ static struct wlr_surface *surface_create(struct wl_client *client,
|
||||||
pixman_region32_init(&surface->input_region);
|
pixman_region32_init(&surface->input_region);
|
||||||
wlr_addon_set_init(&surface->addons);
|
wlr_addon_set_init(&surface->addons);
|
||||||
|
|
||||||
wl_signal_add(&renderer->events.destroy, &surface->renderer_destroy);
|
surface->raster_destroy.notify = surface_handle_raster_destroy;
|
||||||
surface->renderer_destroy.notify = surface_handle_renderer_destroy;
|
|
||||||
|
|
||||||
return surface;
|
return surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_texture *wlr_surface_get_texture(struct wlr_surface *surface) {
|
|
||||||
if (surface->buffer == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return surface->buffer->texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool wlr_surface_has_buffer(struct wlr_surface *surface) {
|
bool wlr_surface_has_buffer(struct wlr_surface *surface) {
|
||||||
return wlr_surface_get_texture(surface) != NULL;
|
return surface->raster != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wlr_surface_set_role(struct wlr_surface *surface,
|
bool wlr_surface_set_role(struct wlr_surface *surface,
|
||||||
|
|
@ -1097,7 +1152,7 @@ static void compositor_create_surface(struct wl_client *client,
|
||||||
struct wlr_compositor *compositor = compositor_from_resource(resource);
|
struct wlr_compositor *compositor = compositor_from_resource(resource);
|
||||||
|
|
||||||
struct wlr_surface *surface = surface_create(client,
|
struct wlr_surface *surface = surface_create(client,
|
||||||
wl_resource_get_version(resource), id, compositor->renderer);
|
wl_resource_get_version(resource), id);
|
||||||
if (surface == NULL) {
|
if (surface == NULL) {
|
||||||
wl_client_post_no_memory(client);
|
wl_client_post_no_memory(client);
|
||||||
return;
|
return;
|
||||||
|
|
@ -1139,8 +1194,7 @@ static void compositor_handle_display_destroy(
|
||||||
free(compositor);
|
free(compositor);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_compositor *wlr_compositor_create(struct wl_display *display,
|
struct wlr_compositor *wlr_compositor_create(struct wl_display *display) {
|
||||||
struct wlr_renderer *renderer) {
|
|
||||||
struct wlr_compositor *compositor = calloc(1, sizeof(*compositor));
|
struct wlr_compositor *compositor = calloc(1, sizeof(*compositor));
|
||||||
if (!compositor) {
|
if (!compositor) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -1152,7 +1206,6 @@ struct wlr_compositor *wlr_compositor_create(struct wl_display *display,
|
||||||
free(compositor);
|
free(compositor);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
compositor->renderer = renderer;
|
|
||||||
|
|
||||||
wl_signal_init(&compositor->events.new_surface);
|
wl_signal_init(&compositor->events.new_surface);
|
||||||
wl_signal_init(&compositor->events.destroy);
|
wl_signal_init(&compositor->events.destroy);
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,10 @@ struct wlr_dmabuf_v1_buffer *wlr_dmabuf_v1_buffer_from_buffer_resource(
|
||||||
|
|
||||||
static const struct wlr_buffer_impl buffer_impl;
|
static const struct wlr_buffer_impl buffer_impl;
|
||||||
|
|
||||||
|
bool wlr_dmabuf_v1_buffer_is_buffer(struct wlr_buffer *buffer) {
|
||||||
|
return buffer->impl == &buffer_impl;
|
||||||
|
}
|
||||||
|
|
||||||
static struct wlr_dmabuf_v1_buffer *dmabuf_v1_buffer_from_buffer(
|
static struct wlr_dmabuf_v1_buffer *dmabuf_v1_buffer_from_buffer(
|
||||||
struct wlr_buffer *buffer) {
|
struct wlr_buffer *buffer) {
|
||||||
assert(buffer->impl == &buffer_impl);
|
assert(buffer->impl == &buffer_impl);
|
||||||
|
|
@ -197,17 +201,15 @@ static void buffer_handle_resource_destroy(struct wl_resource *buffer_resource)
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool check_import_dmabuf(struct wlr_linux_dmabuf_v1 *linux_dmabuf,
|
static bool check_import_dmabuf(struct wlr_linux_dmabuf_v1 *linux_dmabuf,
|
||||||
struct wlr_dmabuf_attributes *attribs) {
|
struct wlr_buffer *dmabuf) {
|
||||||
struct wlr_texture *texture =
|
struct wlr_raster *raster = wlr_raster_create(dmabuf);
|
||||||
wlr_texture_from_dmabuf(linux_dmabuf->renderer, attribs);
|
if (!raster) {
|
||||||
if (texture == NULL) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can import the image, good. No need to keep it since wlr_surface will
|
bool success = wlr_renderer_raster_upload(linux_dmabuf->renderer, raster);
|
||||||
// import it again on commit.
|
wlr_raster_unlock(raster);
|
||||||
wlr_texture_destroy(texture);
|
return success;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void params_create_common(struct wl_resource *params_resource,
|
static void params_create_common(struct wl_resource *params_resource,
|
||||||
|
|
@ -327,17 +329,19 @@ static void params_create_common(struct wl_resource *params_resource,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if dmabuf is usable */
|
|
||||||
if (!check_import_dmabuf(linux_dmabuf, &attribs)) {
|
|
||||||
goto err_failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_dmabuf_v1_buffer *buffer = calloc(1, sizeof(*buffer));
|
struct wlr_dmabuf_v1_buffer *buffer = calloc(1, sizeof(*buffer));
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
wl_resource_post_no_memory(params_resource);
|
wl_resource_post_no_memory(params_resource);
|
||||||
goto err_failed;
|
goto err_failed;
|
||||||
}
|
}
|
||||||
wlr_buffer_init(&buffer->base, &buffer_impl, attribs.width, attribs.height);
|
wlr_buffer_init(&buffer->base, &buffer_impl, attribs.width, attribs.height);
|
||||||
|
buffer->attributes = attribs;
|
||||||
|
|
||||||
|
/* Check if dmabuf is usable */
|
||||||
|
if (!check_import_dmabuf(linux_dmabuf, &buffer->base)) {
|
||||||
|
free(buffer);
|
||||||
|
goto err_failed;
|
||||||
|
}
|
||||||
|
|
||||||
struct wl_client *client = wl_resource_get_client(params_resource);
|
struct wl_client *client = wl_resource_get_client(params_resource);
|
||||||
buffer->resource = wl_resource_create(client, &wl_buffer_interface,
|
buffer->resource = wl_resource_create(client, &wl_buffer_interface,
|
||||||
|
|
@ -350,8 +354,6 @@ static void params_create_common(struct wl_resource *params_resource,
|
||||||
wl_resource_set_implementation(buffer->resource,
|
wl_resource_set_implementation(buffer->resource,
|
||||||
&wl_buffer_impl, buffer, buffer_handle_resource_destroy);
|
&wl_buffer_impl, buffer, buffer_handle_resource_destroy);
|
||||||
|
|
||||||
buffer->attributes = attribs;
|
|
||||||
|
|
||||||
buffer->release.notify = buffer_handle_release;
|
buffer->release.notify = buffer_handle_release;
|
||||||
wl_signal_add(&buffer->base.events.release, &buffer->release);
|
wl_signal_add(&buffer->base.events.release, &buffer->release);
|
||||||
|
|
||||||
|
|
|
||||||
103
types/wlr_raster.c
Normal file
103
types/wlr_raster.c
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
#include <assert.h>
|
||||||
|
#include <wlr/types/wlr_raster.h>
|
||||||
|
#include <wlr/types/wlr_buffer.h>
|
||||||
|
#include <wlr/render/wlr_texture.h>
|
||||||
|
#include "types/wlr_buffer.h"
|
||||||
|
#include "util/signal.h"
|
||||||
|
|
||||||
|
struct wlr_raster *wlr_raster_create(struct wlr_buffer *buffer) {
|
||||||
|
struct wlr_raster *raster = calloc(1, sizeof(*raster));
|
||||||
|
if (!raster) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_list_init(&raster->sources);
|
||||||
|
wl_signal_init(&raster->events.destroy);
|
||||||
|
|
||||||
|
assert(buffer);
|
||||||
|
raster->width = buffer->width;
|
||||||
|
raster->height = buffer->height;
|
||||||
|
raster->buffer = wlr_buffer_lock(buffer);
|
||||||
|
|
||||||
|
raster->n_locks = 1;
|
||||||
|
|
||||||
|
return raster;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_raster_remove_buffer(struct wlr_raster *raster) {
|
||||||
|
assert(raster->buffer);
|
||||||
|
assert(!wl_list_empty(&raster->sources));
|
||||||
|
|
||||||
|
wlr_buffer_unlock(raster->buffer);
|
||||||
|
raster->buffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void raster_consider_destroy(struct wlr_raster *raster) {
|
||||||
|
if (raster->n_locks > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_signal_emit_safe(&raster->events.destroy, NULL);
|
||||||
|
|
||||||
|
struct wlr_texture *texture, *texture_tmp;
|
||||||
|
wl_list_for_each_safe(texture, texture_tmp, &raster->sources, link) {
|
||||||
|
wlr_texture_destroy(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_buffer_unlock(raster->buffer);
|
||||||
|
free(raster);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_raster *wlr_raster_lock(struct wlr_raster *raster) {
|
||||||
|
raster->n_locks++;
|
||||||
|
return raster;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_raster_unlock(struct wlr_raster *raster) {
|
||||||
|
if (!raster) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(raster->n_locks > 0);
|
||||||
|
|
||||||
|
raster->n_locks--;
|
||||||
|
raster_consider_destroy(raster);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_raster_attach(struct wlr_raster *raster, struct wlr_texture *texture) {
|
||||||
|
assert(texture);
|
||||||
|
assert(!texture->raster);
|
||||||
|
assert(texture->width == raster->width && texture->height == raster->height);
|
||||||
|
|
||||||
|
wl_list_insert(&raster->sources, &texture->link);
|
||||||
|
texture->raster = raster;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_raster_detach(struct wlr_raster *raster, struct wlr_texture *texture) {
|
||||||
|
if (!texture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(texture->raster == raster);
|
||||||
|
texture->raster = NULL;
|
||||||
|
wl_list_remove(&texture->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_raster *wlr_raster_from_pixels(uint32_t fmt, uint32_t stride,
|
||||||
|
uint32_t width, uint32_t height, const void *data) {
|
||||||
|
assert(data);
|
||||||
|
|
||||||
|
struct wlr_readonly_data_buffer *buffer =
|
||||||
|
readonly_data_buffer_create(fmt, stride, width, height, data);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_raster *raster = wlr_raster_create(&buffer->base);
|
||||||
|
|
||||||
|
// By this point, the renderer should have locked the buffer if it still
|
||||||
|
// needs to access it in the future.
|
||||||
|
readonly_data_buffer_drop(buffer);
|
||||||
|
|
||||||
|
return raster;
|
||||||
|
}
|
||||||
|
|
@ -226,14 +226,18 @@ static bool frame_shm_copy(struct wlr_screencopy_frame_v1 *frame,
|
||||||
static bool blit_dmabuf(struct wlr_renderer *renderer,
|
static bool blit_dmabuf(struct wlr_renderer *renderer,
|
||||||
struct wlr_dmabuf_v1_buffer *dst_dmabuf,
|
struct wlr_dmabuf_v1_buffer *dst_dmabuf,
|
||||||
struct wlr_buffer *src_buffer) {
|
struct wlr_buffer *src_buffer) {
|
||||||
struct wlr_buffer *dst_buffer = wlr_buffer_lock(&dst_dmabuf->base);
|
struct wlr_raster *raster = wlr_raster_create(src_buffer);
|
||||||
|
if (!raster){
|
||||||
struct wlr_texture *src_tex =
|
return false;
|
||||||
wlr_texture_from_buffer(renderer, src_buffer);
|
|
||||||
if (src_tex == NULL) {
|
|
||||||
goto error_src_tex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!wlr_renderer_raster_upload(renderer, raster)) {
|
||||||
|
wlr_raster_unlock(raster);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_buffer *dst_buffer = wlr_buffer_lock(&dst_dmabuf->base);
|
||||||
|
|
||||||
float mat[9];
|
float mat[9];
|
||||||
wlr_matrix_identity(mat);
|
wlr_matrix_identity(mat);
|
||||||
wlr_matrix_scale(mat, dst_buffer->width, dst_buffer->height);
|
wlr_matrix_scale(mat, dst_buffer->width, dst_buffer->height);
|
||||||
|
|
@ -243,17 +247,16 @@ static bool blit_dmabuf(struct wlr_renderer *renderer,
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_renderer_clear(renderer, (float[]){ 0.0, 0.0, 0.0, 0.0 });
|
wlr_renderer_clear(renderer, (float[]){ 0.0, 0.0, 0.0, 0.0 });
|
||||||
wlr_render_texture_with_matrix(renderer, src_tex, mat, 1.0f);
|
wlr_render_raster_with_matrix(renderer, raster, mat, 1.0f);
|
||||||
|
|
||||||
wlr_renderer_end(renderer);
|
wlr_renderer_end(renderer);
|
||||||
|
|
||||||
wlr_texture_destroy(src_tex);
|
wlr_raster_unlock(raster);
|
||||||
wlr_buffer_unlock(dst_buffer);
|
wlr_buffer_unlock(dst_buffer);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
error_renderer_begin:
|
error_renderer_begin:
|
||||||
wlr_texture_destroy(src_tex);
|
wlr_raster_unlock(raster);
|
||||||
error_src_tex:
|
|
||||||
wlr_buffer_unlock(dst_buffer);
|
wlr_buffer_unlock(dst_buffer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue