wlr_raster: Implement CPU blits

We need this really slow path if the user is using GPUs that don't have
common compatible modifiers. One example of a vendor that doesn't support
rendering to a LINEAR modifier (which otherwise should always exist)
is NVIDIA.
This commit is contained in:
Alexander Orzechowski 2024-02-27 14:47:38 -05:00
parent df20cd28d0
commit 21b04a8c7f

View file

@ -298,6 +298,47 @@ static struct wlr_texture *raster_try_texture_from_blit(struct wlr_raster *raste
return wlr_texture_from_buffer(renderer, imported);
}
static struct wlr_texture *raster_try_cpu_copy(struct wlr_raster *raster,
struct wlr_renderer *dst) {
if (wl_list_empty(&raster->sources)) {
return NULL;
}
wlr_log(WLR_DEBUG, "Performing multigpu blit through the CPU");
struct wlr_texture *texture = NULL;
uint32_t format = DRM_FORMAT_ARGB8888;
uint32_t stride = raster->width * 4;
void *data = malloc(stride * raster->height);
if (!data) {
return NULL;
}
struct wlr_raster_source *source;
wl_list_for_each(source, &raster->sources, link) {
if (!wlr_texture_read_pixels(source->texture, &(struct wlr_texture_read_pixels_options){
.format = format,
.stride = stride,
.data = data,
})) {
wlr_log(WLR_ERROR, "Failed to read pixels");
continue;
}
texture = wlr_texture_from_pixels(dst, format,
stride, raster->width, raster->height, data);
if (!texture) {
wlr_log(WLR_ERROR, "Failed to upload texture from cpu data");
continue;
}
break;
}
free(data);
return texture;
}
struct wlr_texture *wlr_raster_obtain_texture_with_allocator(struct wlr_raster *raster,
struct wlr_renderer *renderer, struct wlr_allocator *allocator) {
struct wlr_texture *texture = wlr_raster_get_texture(raster, renderer);
@ -327,6 +368,13 @@ struct wlr_texture *wlr_raster_obtain_texture_with_allocator(struct wlr_raster *
return texture;
}
// as a last resort we need to do a copy through the CPU
texture = raster_try_cpu_copy(raster, renderer);
if (texture) {
raster_attach_with_allocator(raster, texture, allocator);
return texture;
}
return NULL;
}