Skip to content
This repository has been archived by the owner on Nov 1, 2021. It is now read-only.

Commit

Permalink
render/pixman: implement texture_from_buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
emersion committed Apr 27, 2021
1 parent 768f5ae commit df0436c
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 15 deletions.
7 changes: 5 additions & 2 deletions include/render/pixman.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,12 @@ struct wlr_pixman_texture {
struct wlr_pixman_renderer *renderer;
struct wl_list link; // wlr_pixman_renderer.textures

void *data;
pixman_image_t *image;
const struct wlr_pixel_format_info *format;
pixman_format_code_t format;
const struct wlr_pixel_format_info *format_info;

void *data; // if created via texture_from_pixels
struct wlr_buffer *buffer; // if created via texture_from_buffer
};

pixman_format_code_t get_pixman_format_from_drm(uint32_t fmt);
Expand Down
75 changes: 62 additions & 13 deletions render/pixman/renderer.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,14 @@ static struct wlr_pixman_texture *get_texture(

static bool texture_is_opaque(struct wlr_texture *wlr_texture) {
struct wlr_pixman_texture *texture = get_texture(wlr_texture);
return texture->format->has_alpha;
return texture->format_info->has_alpha;
}

static void texture_destroy(struct wlr_texture *wlr_texture) {
struct wlr_pixman_texture *texture = get_texture(wlr_texture);
wl_list_remove(&texture->link);
pixman_image_unref(texture->image);
wlr_buffer_unlock(texture->buffer);
free(texture->data);
free(texture);
}
Expand Down Expand Up @@ -268,53 +269,100 @@ static const struct wlr_drm_format_set *pixman_get_render_formats(
return &renderer->drm_formats;
}

static struct wlr_texture *pixman_texture_from_pixels(
struct wlr_renderer *wlr_renderer, uint32_t drm_format,
uint32_t stride, uint32_t width, uint32_t height, const void *data) {
struct wlr_pixman_renderer *renderer = get_renderer(wlr_renderer);
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(WLR_ERROR, "Failed to allocate pixman texture");
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 = drm_get_pixel_format_info(drm_format);
if (!texture->format) {
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;
}

pixman_format_code_t format = get_pixman_format_from_drm(drm_format);
if (format == 0) {
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_pixels(
struct wlr_renderer *wlr_renderer, uint32_t drm_format,
uint32_t stride, uint32_t width, uint32_t height, const void *data) {
struct wlr_pixman_renderer *renderer = get_renderer(wlr_renderer);

struct wlr_pixman_texture *texture =
pixman_texture_create(renderer, drm_format, width, height);
if (texture == NULL) {
return NULL;
}

// TODO: avoid this copy
texture->data = malloc(stride * height);
if (texture->data == NULL) {
wlr_log_errno(WLR_ERROR, "Allocation failed");
wl_list_remove(&texture->link);
free(texture);
return NULL;
}
memcpy(texture->data, data, stride * height);

texture->image = pixman_image_create_bits_no_clear(format, width, height,
texture->data, stride);
texture->image = pixman_image_create_bits_no_clear(texture->format,
width, height, texture->data, stride);
if (!texture->image) {
wlr_log(WLR_ERROR, "Failed to create pixman image");
wl_list_remove(&texture->link);
free(texture->data);
free(texture);
return NULL;
}

wl_list_insert(&renderer->textures, &texture->link);
return &texture->wlr_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 (!buffer_get_data_ptr(buffer, &data, &drm_format, &stride)) {
return NULL;
}

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;
}
Expand Down Expand Up @@ -412,6 +460,7 @@ static const struct wlr_renderer_impl renderer_impl = {
.get_shm_texture_formats = pixman_get_shm_texture_formats,
.get_render_formats = pixman_get_render_formats,
.texture_from_pixels = pixman_texture_from_pixels,
.texture_from_buffer = pixman_texture_from_buffer,
.bind_buffer = pixman_bind_buffer,
.destroy = pixman_destroy,
.preferred_read_format = pixman_preferred_read_format,
Expand Down

0 comments on commit df0436c

Please sign in to comment.