Changeset 38c822e in mainline for uspace/srv/hid/rfb/rfb.c


Ignore:
Timestamp:
2013-09-12T13:38:24Z (11 years ago)
Author:
Martin Sucha <sucha14@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
47b27b40
Parents:
2c9f6dd3
Message:

rfb: add very basic support for TRLE encoding

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/hid/rfb/rfb.c

    r2c9f6dd3 r38c822e  
    180180       
    181181        rfb->name = str_dup(name);
     182        rfb->supports_trle = false;
    182183       
    183184        return rfb_set_size(rfb, width, height);
     
    333334}
    334335
     336static size_t rfb_rect_encode_raw(rfb_t *rfb, rfb_rectangle_t *rect, void *buf)
     337{
     338        size_t pixel_size = rfb->pixel_format.bpp / 8;
     339        size_t size = (rect->width * rect->height * pixel_size);
     340       
     341        if (buf == NULL)
     342                return size;
     343       
     344        for (uint16_t y = 0; y < rect->height; y++) {
     345                for (uint16_t x = 0; x < rect->width; x++) {
     346                        pixel_t pixel = pixelmap_get_pixel(&rfb->framebuffer,
     347                            x + rect->x, y + rect->y);
     348                        rfb_encode_pixel(rfb, buf, pixel);
     349                        buf += pixel_size;
     350                }
     351        }
     352       
     353        return size;
     354}
     355
     356typedef enum {
     357        COMP_NONE, COMP_SKIP_START, COMP_SKIP_END
     358} cpixel_compress_type_t;
     359
     360typedef struct {
     361        size_t size;
     362        cpixel_compress_type_t compress_type;
     363} cpixel_ctx_t;
     364
     365static void cpixel_context_init(cpixel_ctx_t *ctx, rfb_pixel_format_t *pixel_format)
     366{
     367        ctx->size = pixel_format->bpp / 8;
     368        ctx->compress_type = COMP_NONE;
     369       
     370        if (pixel_format->bpp == 32 && pixel_format->depth <= 24) {
     371                uint32_t mask = 0;
     372                mask |= pixel_format->r_max << pixel_format->r_shift;
     373                mask |= pixel_format->g_max << pixel_format->g_shift;
     374                mask |= pixel_format->b_max << pixel_format->b_shift;
     375               
     376                if (pixel_format->big_endian) {
     377                        mask = host2uint32_t_be(mask);
     378                }
     379                else {
     380                        mask = host2uint32_t_le(mask);
     381                }
     382               
     383                uint8_t *mask_data = (uint8_t *) &mask;
     384                if (mask_data[0] == 0) {
     385                        ctx->compress_type = COMP_SKIP_START;
     386                        ctx->size = 3;
     387                }
     388                else if (mask_data[3] == 0) {
     389                        ctx->compress_type = COMP_SKIP_END;
     390                        ctx->size = 3;
     391                }
     392        }
     393}
     394
     395static void cpixel_encode(rfb_t *rfb, cpixel_ctx_t *cpixel, void *buf,
     396    pixel_t pixel)
     397{
     398        uint8_t data[4];
     399        rfb_encode_pixel(rfb, data, pixel);
     400       
     401        switch (cpixel->compress_type) {
     402        case COMP_NONE:
     403        case COMP_SKIP_END:
     404                memcpy(buf, data, cpixel->size);
     405                break;
     406        case COMP_SKIP_START:
     407                memcpy(buf, data + 1, cpixel->size);
     408        }
     409}
     410
     411static ssize_t rfb_tile_encode_raw(rfb_t *rfb, cpixel_ctx_t *cpixel,
     412    rfb_rectangle_t *tile, void *buf)
     413{
     414        ssize_t size = tile->width * tile->height * cpixel->size;
     415        if (buf == NULL)
     416                return size;
     417       
     418        for (uint16_t y = tile->y; y < tile->y + tile->height; y++) {
     419                for (uint16_t x = tile->x; x < tile->x + tile->width; x++) {
     420                        pixel_t pixel = pixelmap_get_pixel(&rfb->framebuffer, x, y);
     421                        cpixel_encode(rfb, cpixel, buf, pixel);
     422                }
     423        }
     424       
     425        return size;
     426}
     427
     428static ssize_t rfb_tile_encode_solid(rfb_t *rfb, cpixel_ctx_t *cpixel,
     429    rfb_rectangle_t *tile, void *buf)
     430{
     431        /* Check if it is single color */
     432        pixel_t the_color = pixelmap_get_pixel(&rfb->framebuffer, tile->x, tile->y);
     433        for (uint16_t y = tile->y; y < tile->y + tile->height; y++) {
     434                for (uint16_t x = tile->x; x < tile->x + tile->width; x++) {
     435                        if (pixelmap_get_pixel(&rfb->framebuffer, x, y) != the_color)
     436                                return -1;
     437                }
     438        }
     439       
     440        /* OK, encode it */
     441        if (buf)
     442                cpixel_encode(rfb, cpixel, buf, the_color);
     443        return cpixel->size;
     444}
     445
     446static size_t rfb_rect_encode_trle(rfb_t *rfb, rfb_rectangle_t *rect, void *buf)
     447{
     448        cpixel_ctx_t cpixel;
     449        cpixel_context_init(&cpixel, &rfb->pixel_format);
     450       
     451        size_t size = 0;
     452        for (uint16_t y = 0; y < rect->height; y += 16) {
     453                for (uint16_t x = 0; x < rect->width; x += 16) {
     454                        rfb_rectangle_t tile = {
     455                                .x = x,
     456                                .y = y,
     457                                .width = (x + 16 <= rect->width ? 16 : rect->width - x),
     458                                .height = (y + 16 <= rect->height ? 16 : rect->height - y)
     459                        };
     460                       
     461                        size += 1;
     462                        uint8_t *tile_enctype_ptr = buf;
     463                        if (buf)
     464                                buf +=  1;
     465                       
     466                        uint8_t tile_enctype = RFB_TILE_ENCODING_SOLID;
     467                        ssize_t tile_size = rfb_tile_encode_solid(rfb, &cpixel, &tile, buf);
     468                        if (tile_size < 0) {
     469                                tile_size = rfb_tile_encode_raw(rfb, &cpixel, &tile, buf);
     470                                tile_enctype = RFB_TILE_ENCODING_RAW;
     471                        }
     472                       
     473                        if (buf) {
     474                                *tile_enctype_ptr = tile_enctype;
     475                                buf += tile_size;
     476                        }
     477                }
     478        }
     479        return size;
     480}
     481
    335482static int rfb_send_framebuffer_update(rfb_t *rfb, int conn_sd, bool incremental)
    336483{
     
    346493        size_t buf_size = sizeof(rfb_framebuffer_update_t) +
    347494            sizeof(rfb_rectangle_t) * 1 +
    348             (rfb->damage_rect.width * rfb->damage_rect.height * (rfb->pixel_format.bpp/8));
     495            rfb_rect_encode_raw(rfb, &rfb->damage_rect, NULL)
     496            ;
    349497       
    350498        void *buf = malloc(buf_size);
     
    361509       
    362510        rfb_rectangle_t *rect = pos;
     511        pos += sizeof(rfb_rectangle_t);
     512       
    363513        *rect = rfb->damage_rect;
    364         rect->enctype = RFB_ENCODING_RAW;
     514       
     515        if (rfb->supports_trle) {
     516                rect->enctype = RFB_ENCODING_TRLE;
     517                pos += rfb_rect_encode_trle(rfb, rect, pos);
     518        }
     519        else {
     520                rect->enctype = RFB_ENCODING_RAW;
     521                pos += rfb_rect_encode_raw(rfb, rect, pos);
     522        }
    365523        rfb_rectangle_to_be(rect, rect);
    366         pos += sizeof(rfb_rectangle_t);
    367        
    368         size_t pixel_size = rfb->pixel_format.bpp / 8;
    369        
    370         for (uint16_t y = 0; y < rfb->damage_rect.height; y++) {
    371                 for (uint16_t x = 0; x < rfb->damage_rect.width; x++) {
    372                         pixel_t pixel = pixelmap_get_pixel(&rfb->framebuffer,
    373                             x + rfb->damage_rect.x, y + rfb->damage_rect.y);
    374                         rfb_encode_pixel(rfb, pos, pixel);
    375                         pos += pixel_size;
    376                 }
    377         }
    378524       
    379525        if (!rfb->pixel_format.true_color) {
     
    505651                                        return;
    506652                                encoding = uint32_t_be2host(encoding);
     653                                if (encoding == RFB_ENCODING_TRLE)
     654                                        rfb->supports_trle = true;
     655                               
    507656                        }
    508657                        printf("set encodings\n");
Note: See TracChangeset for help on using the changeset viewer.