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 "frame-capture.h"
#include "smooth.h"
#include "buffer.h"
struct zwlr_screencopy_manager_v1;
struct zwlr_screencopy_frame_v1;
@ -40,11 +41,9 @@ enum screencopy_status {
struct screencopy {
struct frame_capture frame_capture;
struct wl_shm* wl_shm;
struct wl_buffer* buffer;
void* pixels;
size_t bufsize;
struct wv_buffer_pool* pool;
struct wv_buffer* front;
struct wv_buffer* back;
struct zwlr_screencopy_manager_v1* manager;
struct zwlr_screencopy_frame_v1* frame;

View File

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

View File

@ -106,6 +106,8 @@ void wayvnc_exit(struct wayvnc* self);
void on_capture_done(struct frame_capture* capture);
static void on_render(struct nvnc_display* display, struct nvnc_fb* fb);
struct wl_shm* wl_shm = NULL;
static enum frame_capture_backend_type
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) {
self->screencopy_backend.wl_shm
= wl_registry_bind(registry, id, &wl_shm_interface, 1);
wl_shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
return;
}
@ -241,7 +242,7 @@ void wayvnc_destroy(struct wayvnc* self)
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_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 wayvnc* self = nvnc_get_userdata(nvnc);
struct pixman_box16* ext = pixman_region_extents(&self->current_damage);
uint32_t y = ext->y1;
uint32_t damage_height = ext->y2 - ext->y1;
if (!self->screencopy_backend.back)
return;
uint32_t* addr = nvnc_fb_get_addr(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);
// XXX: This releases the buffer for now
frame_capture_render(self->capture_backend, &self->renderer, fb);
}
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)
{
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 height = output_get_transformed_height(self->selected_output);
bool is_first_frame = false;
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);
is_first_frame = true;
} else {
@ -538,11 +571,9 @@ void wayvnc_process_frame(struct wayvnc* self)
assert(height == nvnc_fb_get_height(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) {
uint32_t hint_x = self->capture_backend->damage_hint.x;
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);
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) {
log_error("Failed to start capture. Exiting...\n");

View File

@ -24,6 +24,8 @@
#include <libdrm/drm_fourcc.h>
#include <aml.h>
#include "wlr-screencopy-unstable-v1.h"
#include "buffer.h"
#include "frame-capture.h"
#include "shm.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)
{
struct screencopy* self = (void*)fc;
@ -107,34 +67,41 @@ static void screencopy_buffer(void* 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;
screencopy_stop(&self->frame_capture);
self->frame_capture.on_done(&self->frame_capture);
}
self->frame_capture.frame_info.fourcc_format =
fourcc_from_wl_shm(format);
buffer->y_inverted = true;
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.height = height;
self->frame_capture.frame_info.stride = stride;
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
zwlr_screencopy_frame_v1_copy_with_damage(self->frame,
self->buffer);
buffer->wl_buffer);
}
static void screencopy_flags(void* data,
struct zwlr_screencopy_frame_v1* frame,
uint32_t flags)
{
(void)data;
struct screencopy* self = data;
(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,
@ -165,6 +132,11 @@ static void screencopy_ready(void* data,
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.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,
struct renderer* renderer, struct nvnc_fb* fb)
{
struct screencopy* self = (void*)fc;
/*
uint32_t width = fc->frame_info.width;
uint32_t height = fc->frame_info.height;
uint32_t stride = fc->frame_info.stride;
uint32_t format = fc->frame_info.fourcc_format;
render_framebuffer(renderer, self->pixels, format, width, height, stride);
*/
}
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);
assert(self->timer);
@ -287,6 +262,10 @@ void screencopy_destroy(struct screencopy* self)
aml_stop(aml_get_default(), self->timer);
aml_unref(self->timer);
if (self->buffer)
wl_buffer_destroy(self->buffer);
if (self->back)
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);
}