aboutsummaryrefslogtreecommitdiff
path: root/render
diff options
context:
space:
mode:
Diffstat (limited to 'render')
-rw-r--r--render/gles2/texture.c46
-rw-r--r--render/vulkan/texture.c47
-rw-r--r--render/wlr_texture.c20
3 files changed, 87 insertions, 26 deletions
diff --git a/render/gles2/texture.c b/render/gles2/texture.c
index d794e436..8b4ce673 100644
--- a/render/gles2/texture.c
+++ b/render/gles2/texture.c
@@ -44,14 +44,24 @@ static bool check_stride(const struct wlr_pixel_format_info *fmt,
return true;
}
-static bool gles2_texture_write_pixels(struct wlr_texture *wlr_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) {
+static bool gles2_texture_update_from_buffer(struct wlr_texture *wlr_texture,
+ struct wlr_buffer *buffer, pixman_region32_t *damage) {
struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture);
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;
}
@@ -63,7 +73,8 @@ static bool gles2_texture_write_pixels(struct wlr_texture *wlr_texture,
drm_get_pixel_format_info(texture->drm_format);
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;
}
@@ -75,12 +86,21 @@ static bool gles2_texture_write_pixels(struct wlr_texture *wlr_texture,
glBindTexture(GL_TEXTURE_2D, texture->tex);
- glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / (drm_fmt->bpp / 8));
- glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, src_x);
- glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, src_y);
+ int rects_len = 0;
+ pixman_box32_t *rects = pixman_region32_rectangles(damage, &rects_len);
- glTexSubImage2D(GL_TEXTURE_2D, 0, dst_x, dst_y, width, height,
- fmt->gl_format, fmt->gl_type, data);
+ for (int i = 0; i < rects_len; i++) {
+ 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_SKIP_PIXELS_EXT, 0);
@@ -92,6 +112,8 @@ static bool gles2_texture_write_pixels(struct wlr_texture *wlr_texture,
wlr_egl_restore_context(&prev_ctx);
+ wlr_buffer_end_data_ptr_access(buffer);
+
return true;
}
@@ -156,7 +178,7 @@ static void gles2_texture_unref(struct wlr_texture *wlr_texture) {
}
static const struct wlr_texture_impl texture_impl = {
- .write_pixels = gles2_texture_write_pixels,
+ .update_from_buffer = gles2_texture_update_from_buffer,
.destroy = gles2_texture_unref,
};
diff --git a/render/vulkan/texture.c b/render/vulkan/texture.c
index 35b9562e..88298d93 100644
--- a/render/vulkan/texture.c
+++ b/render/vulkan/texture.c
@@ -136,12 +136,45 @@ static bool write_pixels(struct wlr_texture *wlr_texture,
return true;
}
-static bool vulkan_texture_write_pixels(struct wlr_texture *wlr_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 *vdata) {
- return write_pixels(wlr_texture, stride, width, height, src_x, src_y,
- dst_x, dst_y, vdata, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
- VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT);
+static bool vulkan_texture_update_from_buffer(struct wlr_texture *wlr_texture,
+ struct wlr_buffer *buffer, pixman_region32_t *damage) {
+ struct wlr_vk_texture *texture = vulkan_get_texture(wlr_texture);
+
+ 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) {
@@ -191,7 +224,7 @@ static void vulkan_texture_unref(struct wlr_texture *wlr_texture) {
}
static const struct wlr_texture_impl texture_impl = {
- .write_pixels = vulkan_texture_write_pixels,
+ .update_from_buffer = vulkan_texture_update_from_buffer,
.destroy = vulkan_texture_unref,
};
diff --git a/render/wlr_texture.c b/render/wlr_texture.c
index fa864d02..7a59af30 100644
--- a/render/wlr_texture.c
+++ b/render/wlr_texture.c
@@ -71,13 +71,19 @@ struct wlr_texture *wlr_texture_from_buffer(struct wlr_renderer *renderer,
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) {
+bool wlr_texture_update_from_buffer(struct wlr_texture *texture,
+ struct wlr_buffer *buffer, pixman_region32_t *damage) {
+ if (!texture->impl->update_from_buffer) {
+ return false;
+ }
+ if (texture->width != (uint32_t)buffer->width ||
+ texture->height != (uint32_t)buffer->height) {
+ return false;
+ }
+ const pixman_box32_t *extents = pixman_region32_extents(damage);
+ if (extents->x1 < 0 || extents->y1 < 0 || extents->x2 > buffer->width ||
+ extents->y2 > buffer->height) {
return false;
}
- return texture->impl->write_pixels(texture, stride, width, height,
- src_x, src_y, dst_x, dst_y, data);
+ return texture->impl->update_from_buffer(texture, buffer, damage);
}