wlr_renderer: Introduce wlr_renderer_raster_upload

This commit is contained in:
Alexander Orzechowski 2022-06-24 23:14:12 -04:00
parent 5dd7c00a7c
commit d8def1aa65
10 changed files with 198 additions and 67 deletions

View file

@ -125,6 +125,8 @@ 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_get_texture(
struct wlr_texture *wlr_texture); struct wlr_texture *wlr_texture);
struct wlr_gles2_texture *gles2_raster_upload(struct wlr_gles2_renderer *renderer,
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);

View file

@ -256,6 +256,8 @@ struct wlr_vk_texture {
}; };
struct wlr_vk_texture *vulkan_get_texture(struct wlr_texture *wlr_texture); 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,

View file

@ -27,6 +27,8 @@ 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 (*raster_upload)(struct wlr_renderer *renderer,
struct wlr_raster *raster);
bool (*render_subtexture_with_matrix)(struct wlr_renderer *renderer, bool (*render_subtexture_with_matrix)(struct wlr_renderer *renderer,
struct wlr_texture *texture, const struct wlr_fbox *box, struct wlr_texture *texture, const struct wlr_fbox *box,
const float matrix[static 9], float alpha); const float matrix[static 9], float alpha);

View file

@ -48,6 +48,14 @@ 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);
/**
* 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_renderer_raster_upload(struct wlr_renderer *r,
struct wlr_raster *raster);
/** /**
* Renders the requested texture. * Renders the requested texture.
*/ */

View file

@ -534,6 +534,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,
@ -541,6 +548,7 @@ 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,
.raster_upload = _gles2_raster_upload,
.render_subtexture_with_matrix = gles2_render_subtexture_with_matrix, .render_subtexture_with_matrix = gles2_render_subtexture_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,

View file

@ -376,6 +376,35 @@ 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_raster *wlr_raster) {
struct wlr_texture *texture;
wl_list_for_each(texture, &wlr_raster->sources, link) {
if (wlr_texture_is_gles2(texture)) {
struct wlr_gles2_texture *gles2_tex =
(struct wlr_gles2_texture *)texture;
if (gles2_tex->renderer != renderer) {
continue;
}
return gles2_tex;
}
}
if (!wlr_raster->buffer) {
// we could possibly do a blit with another texture from another renderer,
// but this is unsupported currently.
return NULL;
}
texture = gles2_texture_from_buffer(&renderer->wlr_renderer, wlr_raster->buffer);
if (!texture) {
return NULL;
}
wlr_raster_attach(wlr_raster, texture);
return (struct wlr_gles2_texture *)texture;
}
void wlr_gles2_texture_get_attribs(struct wlr_texture *wlr_texture, void wlr_gles2_texture_get_attribs(struct wlr_texture *wlr_texture,
struct wlr_gles2_texture_attribs *attribs) { struct wlr_gles2_texture_attribs *attribs) {
struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture);

View file

@ -46,8 +46,103 @@ static struct wlr_pixman_texture *get_texture(
return (struct wlr_pixman_texture *)wlr_texture; return (struct wlr_pixman_texture *)wlr_texture;
} }
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 struct wlr_pixman_texture *raster_upload(
struct wlr_pixman_renderer *renderer, struct wlr_raster *wlr_raster) {
struct wlr_texture *texture;
wl_list_for_each(texture, &wlr_raster->sources, link) {
if (wlr_texture_is_pixman(texture)) {
struct wlr_pixman_texture *pixman_tex =
(struct wlr_pixman_texture *)texture;
if (pixman_tex->renderer != renderer) {
continue;
}
return pixman_tex;
}
}
if (!wlr_raster->buffer) {
// we could possibly do a blit with another texture from another renderer,
// but this is unsupported currently.
return NULL;
}
texture = pixman_texture_from_buffer(&renderer->wlr_renderer, wlr_raster->buffer);
if (!texture) {
return NULL;
}
wlr_raster_attach(wlr_raster, texture);
return (struct wlr_pixman_texture *)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);
@ -334,72 +429,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,11 +517,19 @@ 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,
.raster_upload = pixman_raster_upload,
.render_subtexture_with_matrix = pixman_render_subtexture_with_matrix, .render_subtexture_with_matrix = pixman_render_subtexture_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,

View file

@ -976,12 +976,20 @@ 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,
.raster_upload = _vulkan_raster_upload,
.render_subtexture_with_matrix = vulkan_render_subtexture_with_matrix, .render_subtexture_with_matrix = vulkan_render_subtexture_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,

View file

@ -742,3 +742,32 @@ struct wlr_texture *vulkan_texture_from_buffer(
return NULL; return NULL;
} }
} }
struct wlr_vk_texture *vulkan_raster_upload(struct wlr_vk_renderer *renderer,
struct wlr_raster *wlr_raster) {
struct wlr_texture *texture;
wl_list_for_each(texture, &wlr_raster->sources, link) {
if (wlr_texture_is_vk(texture)) {
struct wlr_vk_texture *vk_tex =
(struct wlr_vk_texture *)texture;
if (vk_tex->renderer != renderer) {
continue;
}
return vk_tex;
}
}
if (!wlr_raster->buffer) {
// we could possibly do a blit with another texture from another renderer,
// but this is unsupported currently.
return NULL;
}
texture = vulkan_texture_from_buffer(&renderer->wlr_renderer, wlr_raster->buffer);
if (!texture) {
return NULL;
}
wlr_raster_attach(wlr_raster, texture);
return (struct wlr_vk_texture *)texture;
}

View file

@ -35,6 +35,7 @@ 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->raster_upload);
assert(impl->render_subtexture_with_matrix); assert(impl->render_subtexture_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);
@ -113,6 +114,11 @@ void wlr_renderer_scissor(struct wlr_renderer *r, struct wlr_box *box) {
r->impl->scissor(r, box); r->impl->scissor(r, box);
} }
bool wlr_renderer_raster_upload(struct wlr_renderer *r,
struct wlr_raster *raster) {
return r->impl->raster_upload(r, raster);
}
bool wlr_render_texture(struct wlr_renderer *r, struct wlr_texture *texture, bool wlr_render_texture(struct wlr_renderer *r, struct wlr_texture *texture,
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 = {