tight2: Use worker per stream rather than worker per tile
parent
ed054fe00d
commit
cd2c296fa9
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
struct tight_tile;
|
struct tight_tile;
|
||||||
struct pixman_region16;
|
struct pixman_region16;
|
||||||
|
struct aml_work;
|
||||||
|
|
||||||
struct tight_encoder_v2 {
|
struct tight_encoder_v2 {
|
||||||
uint32_t width;
|
uint32_t width;
|
||||||
|
@ -17,9 +18,7 @@ struct tight_encoder_v2 {
|
||||||
struct tight_tile* grid;
|
struct tight_tile* grid;
|
||||||
|
|
||||||
z_stream zs[4];
|
z_stream zs[4];
|
||||||
uint8_t zs_mask;
|
struct aml_work* zs_worker[4];
|
||||||
pthread_mutex_t zs_mutex;
|
|
||||||
pthread_cond_t zs_cond;
|
|
||||||
|
|
||||||
const struct rfb_pixel_format* dfmt;
|
const struct rfb_pixel_format* dfmt;
|
||||||
const struct rfb_pixel_format* sfmt;
|
const struct rfb_pixel_format* sfmt;
|
||||||
|
|
|
@ -39,12 +39,19 @@ enum tight_tile_state {
|
||||||
|
|
||||||
struct tight_tile {
|
struct tight_tile {
|
||||||
enum tight_tile_state state;
|
enum tight_tile_state state;
|
||||||
struct tight_encoder_v2* parent;
|
|
||||||
size_t size;
|
size_t size;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
char buffer[MAX_TILE_SIZE];
|
char buffer[MAX_TILE_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct tight_zs_worker_ctx {
|
||||||
|
struct tight_encoder_v2* encoder;
|
||||||
|
int index;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void do_tight_zs_work(void*);
|
||||||
|
static void on_tight_zs_work_done(void*);
|
||||||
|
|
||||||
static int tight_encoder_v2_init_stream(z_stream* zs)
|
static int tight_encoder_v2_init_stream(z_stream* zs)
|
||||||
{
|
{
|
||||||
int rc = deflateInit2(zs,
|
int rc = deflateInit2(zs,
|
||||||
|
@ -74,6 +81,27 @@ static inline uint32_t tight_tile_height(struct tight_encoder_v2* self,
|
||||||
return y + TSL > self->height ? self->height - y : TSL;
|
return y + TSL > self->height ? self->height - y : TSL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int tight_init_zs_worker(struct tight_encoder_v2* self, int index)
|
||||||
|
{
|
||||||
|
struct tight_zs_worker_ctx* ctx = calloc(1, sizeof(*ctx));
|
||||||
|
if (!ctx)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ctx->encoder = self;
|
||||||
|
ctx->index = index;
|
||||||
|
|
||||||
|
self->zs_worker[index] =
|
||||||
|
aml_work_new(do_tight_zs_work, on_tight_zs_work_done, ctx, free);
|
||||||
|
if (!self->zs_worker[index])
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
failure:
|
||||||
|
free(ctx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int tight_encoder_v2_init(struct tight_encoder_v2* self, uint32_t width,
|
int tight_encoder_v2_init(struct tight_encoder_v2* self, uint32_t width,
|
||||||
uint32_t height)
|
uint32_t height)
|
||||||
{
|
{
|
||||||
|
@ -90,17 +118,15 @@ int tight_encoder_v2_init(struct tight_encoder_v2* self, uint32_t width,
|
||||||
if (!self->grid)
|
if (!self->grid)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
for (uint32_t y = 0; y < self->grid_height; ++y)
|
|
||||||
for (uint32_t x = 0; x < self->grid_width; ++x)
|
|
||||||
tight_tile(self, x, y)->parent = self;
|
|
||||||
|
|
||||||
tight_encoder_v2_init_stream(&self->zs[0]);
|
tight_encoder_v2_init_stream(&self->zs[0]);
|
||||||
tight_encoder_v2_init_stream(&self->zs[1]);
|
tight_encoder_v2_init_stream(&self->zs[1]);
|
||||||
tight_encoder_v2_init_stream(&self->zs[2]);
|
tight_encoder_v2_init_stream(&self->zs[2]);
|
||||||
tight_encoder_v2_init_stream(&self->zs[3]);
|
tight_encoder_v2_init_stream(&self->zs[3]);
|
||||||
|
|
||||||
pthread_mutex_init(&self->zs_mutex, NULL);
|
tight_init_zs_worker(self, 0);
|
||||||
pthread_cond_init(&self->zs_cond, NULL);
|
tight_init_zs_worker(self, 1);
|
||||||
|
tight_init_zs_worker(self, 2);
|
||||||
|
tight_init_zs_worker(self, 3);
|
||||||
|
|
||||||
pthread_mutex_init(&self->dst_mutex, NULL);
|
pthread_mutex_init(&self->dst_mutex, NULL);
|
||||||
|
|
||||||
|
@ -117,8 +143,10 @@ void tight_encoder_v2_destroy(struct tight_encoder_v2* self)
|
||||||
|
|
||||||
pthread_mutex_destroy(&self->dst_mutex);
|
pthread_mutex_destroy(&self->dst_mutex);
|
||||||
|
|
||||||
pthread_cond_destroy(&self->zs_cond);
|
aml_unref(self->zs_worker[3]);
|
||||||
pthread_mutex_destroy(&self->zs_mutex);
|
aml_unref(self->zs_worker[2]);
|
||||||
|
aml_unref(self->zs_worker[1]);
|
||||||
|
aml_unref(self->zs_worker[0]);
|
||||||
|
|
||||||
deflateEnd(&self->zs[3]);
|
deflateEnd(&self->zs[3]);
|
||||||
deflateEnd(&self->zs[2]);
|
deflateEnd(&self->zs[2]);
|
||||||
|
@ -172,41 +200,6 @@ static int calc_bytes_per_cpixel(const struct rfb_pixel_format* fmt)
|
||||||
: fmt->bits_per_pixel / 8;
|
: fmt->bits_per_pixel / 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tight_acquire_zstream_unlocked(struct tight_encoder_v2* self)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < 4; ++i)
|
|
||||||
if (!(self->zs_mask & (1 << i)))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (i >= 4)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
self->zs_mask |= (1 << i);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tight_acquire_zstream(struct tight_encoder_v2* self)
|
|
||||||
{
|
|
||||||
pthread_mutex_lock(&self->zs_mutex);
|
|
||||||
|
|
||||||
int i;
|
|
||||||
while ((i = tight_acquire_zstream_unlocked(self)) < 0)
|
|
||||||
pthread_cond_wait(&self->zs_cond, &self->zs_mutex);
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&self->zs_mutex);
|
|
||||||
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tight_release_zstream(struct tight_encoder_v2* self, int index)
|
|
||||||
{
|
|
||||||
pthread_mutex_lock(&self->zs_mutex);
|
|
||||||
self->zs_mask &= ~(1 << index);
|
|
||||||
pthread_cond_signal(&self->zs_cond);
|
|
||||||
pthread_mutex_unlock(&self->zs_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tight_deflate(struct tight_tile* tile, void* src,
|
static int tight_deflate(struct tight_tile* tile, void* src,
|
||||||
size_t len, z_stream* zs, bool flush)
|
size_t len, z_stream* zs, bool flush)
|
||||||
{
|
{
|
||||||
|
@ -234,12 +227,9 @@ static int tight_deflate(struct tight_tile* tile, void* src,
|
||||||
|
|
||||||
static void tight_encode_tile_basic(struct tight_encoder_v2* self,
|
static void tight_encode_tile_basic(struct tight_encoder_v2* self,
|
||||||
struct tight_tile* tile, uint32_t x, uint32_t y_start,
|
struct tight_tile* tile, uint32_t x, uint32_t y_start,
|
||||||
uint32_t width, uint32_t height)
|
uint32_t width, uint32_t height, int zs_index)
|
||||||
{
|
{
|
||||||
// TODO Figure out of way to postpone job instead of blocking
|
|
||||||
int zs_index = tight_acquire_zstream(self);
|
|
||||||
z_stream* zs = &self->zs[zs_index];
|
z_stream* zs = &self->zs[zs_index];
|
||||||
|
|
||||||
tile->type = TIGHT_BASIC | TIGHT_STREAM(zs_index);
|
tile->type = TIGHT_BASIC | TIGHT_STREAM(zs_index);
|
||||||
|
|
||||||
int bytes_per_cpixel = calc_bytes_per_cpixel(self->dfmt);
|
int bytes_per_cpixel = calc_bytes_per_cpixel(self->dfmt);
|
||||||
|
@ -270,11 +260,9 @@ static void tight_encode_tile_basic(struct tight_encoder_v2* self,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tight_encode_tile(struct tight_encoder_v2* self,
|
static void tight_encode_tile(struct tight_encoder_v2* self,
|
||||||
struct tight_tile* tile)
|
uint32_t gx, uint32_t gy, int zs_index)
|
||||||
{
|
{
|
||||||
intptr_t index = ((intptr_t)tile - (intptr_t)self->grid) / sizeof(*tile);
|
struct tight_tile* tile = tight_tile(self, gx, gy);
|
||||||
uint32_t gx = index % self->grid_width;
|
|
||||||
uint32_t gy = index / self->grid_width;
|
|
||||||
|
|
||||||
uint32_t x = gx * TSL;
|
uint32_t x = gx * TSL;
|
||||||
uint32_t y = gy * TSL;
|
uint32_t y = gy * TSL;
|
||||||
|
@ -284,7 +272,7 @@ static void tight_encode_tile(struct tight_encoder_v2* self,
|
||||||
|
|
||||||
tile->size = 0;
|
tile->size = 0;
|
||||||
|
|
||||||
tight_encode_tile_basic(self, tile, x, y, width, height);
|
tight_encode_tile_basic(self, tile, x, y, width, height, zs_index);
|
||||||
//TODO Jpeg
|
//TODO Jpeg
|
||||||
|
|
||||||
struct rfb_server_fb_rect rect = {
|
struct rfb_server_fb_rect rect = {
|
||||||
|
@ -296,15 +284,10 @@ static void tight_encode_tile(struct tight_encoder_v2* self,
|
||||||
};
|
};
|
||||||
|
|
||||||
pthread_mutex_lock(&self->dst_mutex);
|
pthread_mutex_lock(&self->dst_mutex);
|
||||||
|
|
||||||
// TODO: Check if the tile is basic before releasing stream
|
|
||||||
tight_release_zstream(self, (tile->type >> 4) & 3);
|
|
||||||
|
|
||||||
vec_append(self->dst, &rect, sizeof(rect));
|
vec_append(self->dst, &rect, sizeof(rect));
|
||||||
vec_append(self->dst, &tile->type, sizeof(tile->type));
|
vec_append(self->dst, &tile->type, sizeof(tile->type));
|
||||||
tight_encode_size(self->dst, tile->size);
|
tight_encode_size(self->dst, tile->size);
|
||||||
vec_append(self->dst, tile->buffer, tile->size);
|
vec_append(self->dst, tile->buffer, tile->size);
|
||||||
|
|
||||||
pthread_mutex_unlock(&self->dst_mutex);
|
pthread_mutex_unlock(&self->dst_mutex);
|
||||||
|
|
||||||
tile->state = TIGHT_TILE_READY;
|
tile->state = TIGHT_TILE_READY;
|
||||||
|
@ -320,17 +303,22 @@ static int tight_encode_rect_count(struct tight_encoder_v2* self)
|
||||||
return vec_append(self->dst, &msg, sizeof(msg));
|
return vec_append(self->dst, &msg, sizeof(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_encode_tile(void* obj)
|
static void do_tight_zs_work(void* obj)
|
||||||
{
|
{
|
||||||
struct tight_tile* tile = aml_get_userdata(obj);
|
struct tight_zs_worker_ctx* ctx = aml_get_userdata(obj);
|
||||||
struct tight_encoder_v2* self = tile->parent;
|
struct tight_encoder_v2* self = ctx->encoder;
|
||||||
tight_encode_tile(self, tile);
|
int index = ctx->index;
|
||||||
|
|
||||||
|
for (uint32_t y = 0; y < self->grid_height; ++y)
|
||||||
|
for (uint32_t x = index; x < self->grid_width; x += 4)
|
||||||
|
if (tight_tile(self, x, y)->state == TIGHT_TILE_DAMAGED)
|
||||||
|
tight_encode_tile(self, x, y, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_encode_tile_done(void* obj)
|
static void on_tight_zs_work_done(void* obj)
|
||||||
{
|
{
|
||||||
struct tight_tile* tile = aml_get_userdata(obj);
|
struct tight_zs_worker_ctx* ctx = aml_get_userdata(obj);
|
||||||
struct tight_encoder_v2* self = tile->parent;
|
struct tight_encoder_v2* self = ctx->encoder;
|
||||||
|
|
||||||
pthread_mutex_lock(&self->wait_mutex);
|
pthread_mutex_lock(&self->wait_mutex);
|
||||||
if (--self->n_jobs == 0)
|
if (--self->n_jobs == 0)
|
||||||
|
@ -338,32 +326,19 @@ static void on_encode_tile_done(void* obj)
|
||||||
pthread_mutex_unlock(&self->wait_mutex);
|
pthread_mutex_unlock(&self->wait_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tight_schedule_encode_tile(struct tight_encoder_v2* self,
|
static int tight_schedule_zs_work(struct tight_encoder_v2* self, int index)
|
||||||
uint32_t x, uint32_t y)
|
|
||||||
{
|
{
|
||||||
struct tight_tile* tile = tight_tile(self, x, y);
|
int rc = aml_start(aml_get_default(), self->zs_worker[index]);
|
||||||
|
|
||||||
if (tile->state != TIGHT_TILE_DAMAGED)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
struct aml_work* work = aml_work_new(do_encode_tile,
|
|
||||||
on_encode_tile_done, tile, NULL);
|
|
||||||
if (!work)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
int rc = aml_start(aml_get_default(), work);
|
|
||||||
if (rc >= 0)
|
if (rc >= 0)
|
||||||
++self->n_jobs;
|
++self->n_jobs;
|
||||||
|
|
||||||
aml_unref(work);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tight_schedule_encoding_jobs(struct tight_encoder_v2* self)
|
static int tight_schedule_encoding_jobs(struct tight_encoder_v2* self)
|
||||||
{
|
{
|
||||||
for (uint32_t y = 0; y < self->grid_height; ++y)
|
for (int i = 0; i < 4; ++i)
|
||||||
for (uint32_t x = 0; x < self->grid_width; ++x)
|
if (tight_schedule_zs_work(self, i) < 0)
|
||||||
if (tight_schedule_encode_tile(self, x, y) < 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue