Example #1
0
static void image_cache_put(SpiceImageCache *spice_cache, uint64_t id, pixman_image_t *image)
{
    ImageCache *cache = SPICE_UPCAST(ImageCache, spice_cache);
    ImageCacheItem *item;

#ifndef IMAGE_CACHE_AGE
    if (cache->num_items == IMAGE_CACHE_MAX_ITEMS) {
        SPICE_VERIFY(SPICE_OFFSETOF(ImageCacheItem, lru_link) == 0);
        ImageCacheItem *tail = (ImageCacheItem *)ring_get_tail(&cache->lru);
        spice_assert(tail);
        image_cache_remove(cache, tail);
    }
#endif

    item = spice_new(ImageCacheItem, 1);
    item->id = id;
#ifdef IMAGE_CACHE_AGE
    item->age = cache->age;
#else
    cache->num_items++;
#endif
    item->image = pixman_image_ref(image);
    ring_item_init(&item->lru_link);

    item->next = cache->hash_table[item->id % IMAGE_CACHE_HASH_SIZE];
    cache->hash_table[item->id % IMAGE_CACHE_HASH_SIZE] = item;

    ring_add(&cache->lru, &item->lru_link);
}
Example #2
0
void image_cache_reset(ImageCache *cache)
{
    ImageCacheItem *item;

    SPICE_VERIFY(SPICE_OFFSETOF(ImageCacheItem, lru_link) == 0);
    while ((item = (ImageCacheItem *)ring_get_head(&cache->lru))) {
        image_cache_remove(cache, item);
    }
#ifdef IMAGE_CACHE_AGE
    cache->age = 0;
#endif
}
Example #3
0
void image_cache_aging(ImageCache *cache)
{
    SPICE_VERIFY(SPICE_OFFSETOF(ImageCacheItem, lru_link) == 0);
#ifdef IMAGE_CACHE_AGE
    ImageCacheItem *item;

    cache->age++;
    while ((item = (ImageCacheItem *)ring_get_tail(&cache->lru)) &&
           cache->age - item->age > IMAGE_CACHE_DEPTH) {
        image_cache_remove(cache, item);
    }
#endif
}
Example #4
0
int main(int argc, char **argv)
{
    RedMemSlotInfo mem_info;
    memslot_info_init(&mem_info, 1 /* groups */, 1 /* slots */, 1, 1, 0);
    memslot_info_add_slot(&mem_info, 0, 0, 0 /* delta */, 0 /* start */, ~0ul /* end */, 0 /* generation */);

    RedSurfaceCmd cmd;
    QXLSurfaceCmd qxl;

    RedCursorCmd red_cursor_cmd;
    QXLCursorCmd cursor_cmd;
    QXLCursor *cursor;
    QXLDataChunk *chunks[2];

    void *surface_mem;

    memset(&qxl, 0, sizeof(qxl));

    qxl.surface_id = 123;

    /* try to create a surface with no issues, should succeed */
    test("no issues");
    qxl.u.surface_create.format = SPICE_SURFACE_FMT_32_xRGB;
    qxl.u.surface_create.width = 128;
    qxl.u.surface_create.stride = 512;
    qxl.u.surface_create.height = 128;
    surface_mem = malloc(0x10000);
    qxl.u.surface_create.data = to_physical(surface_mem);
    if (red_get_surface_cmd(&mem_info, 0, &cmd, to_physical(&qxl)))
        failure();

    /* try to create a surface with a stride too small to fit
     * the entire width.
     * This can be used to cause buffer overflows so refuse it.
     */
    test("stride too small");
    qxl.u.surface_create.stride = 256;
    if (!red_get_surface_cmd(&mem_info, 0, &cmd, to_physical(&qxl)))
        failure();

    /* try to create a surface quite large.
     * The sizes (width and height) were chosen so the multiplication
     * using 32 bit values gives a very small value.
     * These kind of values should be refused as they will cause
     * overflows. Also the total memory for the card is not enough to
     * hold the surface so surely can't be accepted.
     */
    test("too big image");
    qxl.u.surface_create.stride = 0x08000004 * 4;
    qxl.u.surface_create.width = 0x08000004;
    qxl.u.surface_create.height = 0x40000020;
    if (!red_get_surface_cmd(&mem_info, 0, &cmd, to_physical(&qxl)))
        failure();

    /* test base cursor with no problems */
    test("base cursor command");
    memset(&cursor_cmd, 0, sizeof(cursor_cmd));
    cursor_cmd.type = QXL_CURSOR_SET;

    cursor = create_chunk(SPICE_OFFSETOF(QXLCursor, chunk), 128 * 128 * 4, NULL, 0xaa);
    cursor->header.unique = 1;
    cursor->header.width = 128;
    cursor->header.height = 128;
    cursor->data_size = 128 * 128 * 4;

    cursor_cmd.u.set.shape = to_physical(cursor);

    if (red_get_cursor_cmd(&mem_info, 0, &red_cursor_cmd, to_physical(&cursor_cmd)))
        failure();
    free(red_cursor_cmd.u.set.shape.data);
    free(cursor);

    /* a circular list of empty chunks should not be a problems */
    test("circular empty chunks");
    memset(&cursor_cmd, 0, sizeof(cursor_cmd));
    cursor_cmd.type = QXL_CURSOR_SET;

    cursor = create_chunk(SPICE_OFFSETOF(QXLCursor, chunk), 0, NULL, 0xaa);
    cursor->header.unique = 1;
    cursor->header.width = 128;
    cursor->header.height = 128;
    cursor->data_size = 128 * 128 * 4;

    chunks[0] = create_chunk(0, 0, &cursor->chunk, 0xaa);
    chunks[0]->next_chunk = to_physical(&cursor->chunk);

    cursor_cmd.u.set.shape = to_physical(cursor);

    memset(&red_cursor_cmd, 0xaa, sizeof(red_cursor_cmd));
    if (!red_get_cursor_cmd(&mem_info, 0, &red_cursor_cmd, to_physical(&cursor_cmd))) {
        /* function does not return errors so there should be no data */
        assert(red_cursor_cmd.type == QXL_CURSOR_SET);
        assert(red_cursor_cmd.u.set.position.x == 0);
        assert(red_cursor_cmd.u.set.position.y == 0);
        assert(red_cursor_cmd.u.set.shape.data_size == 0);
    }
    free(cursor);
    free(chunks[0]);

    /* a circular list of small chunks should not be a problems */
    test("circular small chunks");
    memset(&cursor_cmd, 0, sizeof(cursor_cmd));
    cursor_cmd.type = QXL_CURSOR_SET;

    cursor = create_chunk(SPICE_OFFSETOF(QXLCursor, chunk), 1, NULL, 0xaa);
    cursor->header.unique = 1;
    cursor->header.width = 128;
    cursor->header.height = 128;
    cursor->data_size = 128 * 128 * 4;

    chunks[0] = create_chunk(0, 1, &cursor->chunk, 0xaa);
    chunks[0]->next_chunk = to_physical(&cursor->chunk);

    cursor_cmd.u.set.shape = to_physical(cursor);

    memset(&red_cursor_cmd, 0xaa, sizeof(red_cursor_cmd));
    if (!red_get_cursor_cmd(&mem_info, 0, &red_cursor_cmd, to_physical(&cursor_cmd))) {
        /* function does not return errors so there should be no data */
        assert(red_cursor_cmd.type == QXL_CURSOR_SET);
        assert(red_cursor_cmd.u.set.position.x == 0);
        assert(red_cursor_cmd.u.set.position.y == 0);
        assert(red_cursor_cmd.u.set.shape.data_size == 0);
    }
    free(cursor);
    free(chunks[0]);

    free(mem_info.mem_slots[0]);
    free(mem_info.mem_slots);
    free(surface_mem);

    return exit_code;
}