Render using pixman

pixman-rendering
Andri Yngvason 2020-06-20 21:07:58 +00:00
parent 03114c80e2
commit 5e5806fcf6
4 changed files with 91 additions and 72 deletions

View File

@ -21,6 +21,7 @@
#include "wlr-screencopy-unstable-v1.h" #include "wlr-screencopy-unstable-v1.h"
#include "frame-capture.h" #include "frame-capture.h"
#include "smooth.h" #include "smooth.h"
#include "buffer.h"
struct zwlr_screencopy_manager_v1; struct zwlr_screencopy_manager_v1;
struct zwlr_screencopy_frame_v1; struct zwlr_screencopy_frame_v1;
@ -40,11 +41,9 @@ enum screencopy_status {
struct screencopy { struct screencopy {
struct frame_capture frame_capture; struct frame_capture frame_capture;
struct wl_shm* wl_shm; struct wv_buffer_pool* pool;
struct wl_buffer* buffer; struct wv_buffer* front;
struct wv_buffer* back;
void* pixels;
size_t bufsize;
struct zwlr_screencopy_manager_v1* manager; struct zwlr_screencopy_manager_v1* manager;
struct zwlr_screencopy_frame_v1* frame; struct zwlr_screencopy_frame_v1* frame;

View File

@ -70,6 +70,7 @@ sources = [
'src/cfg.c', 'src/cfg.c',
'src/intset.c', 'src/intset.c',
'src/damage.c', 'src/damage.c',
'src/buffer.c',
] ]
dependencies = [ dependencies = [

View File

@ -106,6 +106,8 @@ void wayvnc_exit(struct wayvnc* self);
void on_capture_done(struct frame_capture* capture); void on_capture_done(struct frame_capture* capture);
static void on_render(struct nvnc_display* display, struct nvnc_fb* fb); static void on_render(struct nvnc_display* display, struct nvnc_fb* fb);
struct wl_shm* wl_shm = NULL;
static enum frame_capture_backend_type static enum frame_capture_backend_type
frame_capture_backend_from_string(const char* str) frame_capture_backend_from_string(const char* str)
{ {
@ -147,8 +149,7 @@ static void registry_add(void* data, struct wl_registry* registry,
} }
if (strcmp(interface, wl_shm_interface.name) == 0) { if (strcmp(interface, wl_shm_interface.name) == 0) {
self->screencopy_backend.wl_shm wl_shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
= wl_registry_bind(registry, id, &wl_shm_interface, 1);
return; return;
} }
@ -241,7 +242,7 @@ void wayvnc_destroy(struct wayvnc* self)
zxdg_output_manager_v1_destroy(self->xdg_output_manager); zxdg_output_manager_v1_destroy(self->xdg_output_manager);
wl_shm_destroy(self->screencopy_backend.wl_shm); wl_shm_destroy(wl_shm);
zwp_virtual_keyboard_v1_destroy(self->keyboard_backend.virtual_keyboard); zwp_virtual_keyboard_v1_destroy(self->keyboard_backend.virtual_keyboard);
zwp_virtual_keyboard_manager_v1_destroy(self->keyboard_manager); zwp_virtual_keyboard_manager_v1_destroy(self->keyboard_manager);
@ -479,16 +480,48 @@ static void on_render(struct nvnc_display* display, struct nvnc_fb* fb)
struct nvnc* nvnc = nvnc_display_get_server(display); struct nvnc* nvnc = nvnc_display_get_server(display);
struct wayvnc* self = nvnc_get_userdata(nvnc); struct wayvnc* self = nvnc_get_userdata(nvnc);
struct pixman_box16* ext = pixman_region_extents(&self->current_damage); if (!self->screencopy_backend.back)
uint32_t y = ext->y1; return;
uint32_t damage_height = ext->y2 - ext->y1;
uint32_t* addr = nvnc_fb_get_addr(fb); uint32_t* addr = nvnc_fb_get_addr(fb);
uint32_t width = nvnc_fb_get_width(fb); uint32_t width = nvnc_fb_get_width(fb);
uint32_t height = nvnc_fb_get_height(fb);
renderer_read_frame(&self->renderer, addr + y * width, y, damage_height); pixman_image_t* dstimg = pixman_image_create_bits_no_clear(
PIXMAN_x8b8g8r8, width, height, addr, 4 * width);
pixman_image_t* srcimg = self->screencopy_backend.back->image;
#define F1 pixman_fixed_1
pixman_transform_t y_invert = {{
{ F1, 0, 0 },
{ 0, -F1, height * F1 },
{ 0, 0, F1},
}};
#undef F1
pixman_transform_t identity;
pixman_transform_init_identity(&identity);
if (self->screencopy_backend.back->y_inverted)
pixman_image_set_transform(srcimg, &y_invert);
else
pixman_image_set_transform(srcimg, &identity);
pixman_image_set_clip_region(srcimg, &self->current_damage);
pixman_image_composite(PIXMAN_OP_OVER, srcimg, NULL, dstimg,
0, 0,
0, 0,
0, 0,
width, height);
pixman_image_unref(dstimg);
pixman_region_clear(&self->current_damage); pixman_region_clear(&self->current_damage);
// XXX: This releases the buffer for now
frame_capture_render(self->capture_backend, &self->renderer, fb);
} }
static void wayvnc_damage_region(struct wayvnc* self, static void wayvnc_damage_region(struct wayvnc* self,
@ -523,13 +556,13 @@ static void on_damage_check_done(struct pixman_region16* damage, void* userdata)
void wayvnc_process_frame(struct wayvnc* self) void wayvnc_process_frame(struct wayvnc* self)
{ {
uint32_t format = fourcc_from_gl_format(self->renderer.read_format); // uint32_t format = fourcc_from_gl_format(self->renderer.read_format);
uint32_t width = output_get_transformed_width(self->selected_output); uint32_t width = output_get_transformed_width(self->selected_output);
uint32_t height = output_get_transformed_height(self->selected_output); uint32_t height = output_get_transformed_height(self->selected_output);
bool is_first_frame = false; bool is_first_frame = false;
if (!self->buffer) { if (!self->buffer) {
self->buffer = nvnc_fb_new(width, height, format); self->buffer = nvnc_fb_new(width, height, DRM_FORMAT_XBGR8888);
nvnc_display_set_buffer(self->nvnc_display, self->buffer); nvnc_display_set_buffer(self->nvnc_display, self->buffer);
is_first_frame = true; is_first_frame = true;
} else { } else {
@ -538,11 +571,9 @@ void wayvnc_process_frame(struct wayvnc* self)
assert(height == nvnc_fb_get_height(self->buffer)); assert(height == nvnc_fb_get_height(self->buffer));
} }
/*
struct nvnc_fb* fb = self->buffer; struct nvnc_fb* fb = self->buffer;
// TODO: Fix constness on fb in this function
frame_capture_render(self->capture_backend, &self->renderer, fb);
if (!is_first_frame) { if (!is_first_frame) {
uint32_t hint_x = self->capture_backend->damage_hint.x; uint32_t hint_x = self->capture_backend->damage_hint.x;
uint32_t hint_y = self->capture_backend->damage_hint.y; uint32_t hint_y = self->capture_backend->damage_hint.y;
@ -572,8 +603,17 @@ void wayvnc_process_frame(struct wayvnc* self)
on_damage_check_done, self); on_damage_check_done, self);
return; return;
} }
*/
wayvnc_damage_whole(self); int damx = self->capture_backend->damage_hint.x;
int damy = self->capture_backend->damage_hint.y;
int damw = self->capture_backend->damage_hint.width;
int damh = self->capture_backend->damage_hint.height;
struct pixman_region16 damage;
pixman_region_init_rect(&damage, damx, damy, damw, damh);
wayvnc_damage_region(self, &damage);
pixman_region_fini(&damage);
if (wayvnc_start_capture(self, 0) < 0) { if (wayvnc_start_capture(self, 0) < 0) {
log_error("Failed to start capture. Exiting...\n"); log_error("Failed to start capture. Exiting...\n");

View File

@ -24,6 +24,8 @@
#include <libdrm/drm_fourcc.h> #include <libdrm/drm_fourcc.h>
#include <aml.h> #include <aml.h>
#include "wlr-screencopy-unstable-v1.h"
#include "buffer.h"
#include "frame-capture.h" #include "frame-capture.h"
#include "shm.h" #include "shm.h"
#include "screencopy.h" #include "screencopy.h"
@ -44,48 +46,6 @@ static uint32_t fourcc_from_wl_shm(enum wl_shm_format in)
} }
} }
static int screencopy_buffer_init(struct screencopy* self,
enum wl_shm_format format, uint32_t width,
uint32_t height, uint32_t stride)
{
if (self->buffer)
return 0;
size_t size = stride * height;
int fd = shm_alloc_fd(size);
if (fd < 0)
return -1;
void* addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (!addr)
goto mmap_failure;
struct wl_shm_pool* pool = wl_shm_create_pool(self->wl_shm, fd, size);
if (!pool)
goto shm_failure;
struct wl_buffer* buffer =
wl_shm_pool_create_buffer(pool, 0, width, height, stride,
format);
wl_shm_pool_destroy(pool);
if (!buffer)
goto shm_failure;
self->buffer = buffer;
self->pixels = addr;
self->bufsize = size;
close(fd);
return 0;
shm_failure:
munmap(addr, size);
mmap_failure:
close(fd);
return -1;
}
static void screencopy_stop(struct frame_capture* fc) static void screencopy_stop(struct frame_capture* fc)
{ {
struct screencopy* self = (void*)fc; struct screencopy* self = (void*)fc;
@ -107,34 +67,41 @@ static void screencopy_buffer(void* data,
{ {
struct screencopy* self = data; struct screencopy* self = data;
if (screencopy_buffer_init(self, format, width, height, stride) < 0) { uint32_t fourcc = fourcc_from_wl_shm(format);
wv_buffer_pool_resize(self->pool, width, height, stride, fourcc);
struct wv_buffer* buffer = wv_buffer_pool_acquire(self->pool);
if (!buffer) {
self->frame_capture.status = CAPTURE_FATAL; self->frame_capture.status = CAPTURE_FATAL;
screencopy_stop(&self->frame_capture); screencopy_stop(&self->frame_capture);
self->frame_capture.on_done(&self->frame_capture); self->frame_capture.on_done(&self->frame_capture);
} }
self->frame_capture.frame_info.fourcc_format = buffer->y_inverted = true;
fourcc_from_wl_shm(format);
assert(!self->front);
self->front = buffer;
self->frame_capture.frame_info.fourcc_format = fourcc;
self->frame_capture.frame_info.width = width; self->frame_capture.frame_info.width = width;
self->frame_capture.frame_info.height = height; self->frame_capture.frame_info.height = height;
self->frame_capture.frame_info.stride = stride; self->frame_capture.frame_info.stride = stride;
if (self->is_immediate_copy) if (self->is_immediate_copy)
zwlr_screencopy_frame_v1_copy(self->frame, self->buffer); zwlr_screencopy_frame_v1_copy(self->frame, buffer->wl_buffer);
else else
zwlr_screencopy_frame_v1_copy_with_damage(self->frame, zwlr_screencopy_frame_v1_copy_with_damage(self->frame,
self->buffer); buffer->wl_buffer);
} }
static void screencopy_flags(void* data, static void screencopy_flags(void* data,
struct zwlr_screencopy_frame_v1* frame, struct zwlr_screencopy_frame_v1* frame,
uint32_t flags) uint32_t flags)
{ {
(void)data; struct screencopy* self = data;
(void)frame; (void)frame;
(void)flags;
/* TODO. Assume y-invert for now */ // self->buffer->y_inverted = !!(flags & ZWLR_SCREENCOPY_FRAME_V1_FLAGS_Y_INVERT);
} }
static void screencopy_ready(void* data, static void screencopy_ready(void* data,
@ -165,6 +132,11 @@ static void screencopy_ready(void* data,
self->frame_capture.frame_info.height; self->frame_capture.frame_info.height;
} }
if (self->back)
wv_buffer_pool_release(self->pool, self->back);
self->back = self->front;
self->front = NULL;
self->frame_capture.status = CAPTURE_DONE; self->frame_capture.status = CAPTURE_DONE;
self->frame_capture.on_done(&self->frame_capture); self->frame_capture.on_done(&self->frame_capture);
} }
@ -260,18 +232,21 @@ static int screencopy_start(struct frame_capture* fc,
static void screencopy_render(struct frame_capture* fc, static void screencopy_render(struct frame_capture* fc,
struct renderer* renderer, struct nvnc_fb* fb) struct renderer* renderer, struct nvnc_fb* fb)
{ {
struct screencopy* self = (void*)fc; /*
uint32_t width = fc->frame_info.width; uint32_t width = fc->frame_info.width;
uint32_t height = fc->frame_info.height; uint32_t height = fc->frame_info.height;
uint32_t stride = fc->frame_info.stride; uint32_t stride = fc->frame_info.stride;
uint32_t format = fc->frame_info.fourcc_format; uint32_t format = fc->frame_info.fourcc_format;
render_framebuffer(renderer, self->pixels, format, width, height, stride); render_framebuffer(renderer, self->pixels, format, width, height, stride);
*/
} }
void screencopy_init(struct screencopy* self) void screencopy_init(struct screencopy* self)
{ {
self->pool = wv_buffer_pool_create(0, 0, 0, 0);
assert(self->pool);
self->timer = aml_timer_new(0, screencopy__poll, self, NULL); self->timer = aml_timer_new(0, screencopy__poll, self, NULL);
assert(self->timer); assert(self->timer);
@ -287,6 +262,10 @@ void screencopy_destroy(struct screencopy* self)
aml_stop(aml_get_default(), self->timer); aml_stop(aml_get_default(), self->timer);
aml_unref(self->timer); aml_unref(self->timer);
if (self->buffer) if (self->back)
wl_buffer_destroy(self->buffer); wv_buffer_pool_release(self->pool, self->back);
if (self->front)
wv_buffer_pool_release(self->pool, self->front);
wv_buffer_pool_destroy(self->pool);
} }