void process_buffer(vx_gtk_buffer_manager_t * man, vx_code_input_stream_t * cins)
{
    int world_id = cins->read_uint32(cins);
    const char * name = cins->read_str(cins);
    int draw_order = cins->read_uint32(cins);

    // find a matching layer:
    int update = 0;
    pthread_mutex_lock(&man->mutex);
    {
        layer_info_t * linfo = NULL;
        int layer_id = 0;
        zhash_iterator_t itr;
        zhash_iterator_init(man->layers, &itr);
        while(zhash_iterator_next(&itr, &layer_id, &linfo)) {
            if (linfo->world_id == world_id) {
                break;
            }
        }

        if (linfo == NULL) { // XXX Assert?
            pthread_mutex_unlock(&man->mutex);
            return;
        }

        // Now ensure there's a buffer_info_t in this layer.
        buffer_info_t * buffer = NULL;
        int success = zhash_get(linfo->buffers, &name, &buffer);

        // buffer doesn't exist yet?
        if (!success) {
            buffer = calloc(1, sizeof(buffer_info_t));
            buffer->layer_id = linfo->layer_id;
            buffer->name = strdup(name);
            buffer->enabled = 1;
            buffer->draw_order = draw_order;
            buffer->man = man;

            zhash_put(linfo->buffers, &buffer->name, &buffer, NULL, NULL);

            update = 1;
        }

        // draw order changed?
        if (success && draw_order != buffer->draw_order) {
            assert(buffer != NULL);
            buffer->draw_order = draw_order;

            update = 1;
        }
    }
    pthread_mutex_unlock(&man->mutex);

    if (update == 1)
        queue_update_view(man);
}
Example #2
0
// XXX make static
render_info_t * render_info_copy (render_info_t * rinfo)
{
    assert(rinfo != NULL);
    render_info_t * rinfo_copy = render_info_create();

    // copy a list of ints (ordered)
    for (int i = 0; i < zarray_size(rinfo->layers); i++) {
        layer_info_t * layer_info = NULL;
        zarray_get(rinfo->layers, i, &layer_info);
        zarray_add(rinfo_copy->layers, &layer_info);
    }

    // copy all the camera positions
    {
        zhash_iterator_t vit;
        uint32_t layer_id;
        vx_camera_pos_t *pos;
        zhash_iterator_init (rinfo->camera_positions, &vit);
        while (zhash_iterator_next (&vit, &layer_id, &pos)) {
            vx_camera_pos_t *pos_copy = malloc (sizeof(*pos_copy));
            memcpy(pos_copy, pos, sizeof(vx_camera_pos_t));
            zhash_put (rinfo_copy->camera_positions, &layer_id, &pos_copy, NULL, NULL);
        }
    }

    // copy each individual layer viewports
    {
        zhash_iterator_t itr;
        uint32_t layer_id;
        int *viewport;
        zhash_iterator_init (rinfo->layer_positions, &itr);
        while (zhash_iterator_next (&itr, &layer_id, &viewport)) {
            int *viewport_copy = malloc (4*sizeof(int));
            memcpy(viewport_copy, viewport, 4*sizeof(int));
            zhash_put (rinfo_copy->layer_positions, &layer_id, &viewport_copy, NULL, NULL);
        }
    }

    memcpy(rinfo_copy->viewport, rinfo->viewport, 4*sizeof(int));

    return rinfo_copy;
}
Example #3
0
// Add all elements in B to A
static void addAll(zhash_t * A, zhash_t  * B)
{
    zhash_iterator_t itr;
    zhash_iterator_init(B, &itr);
    uint64_t id = -1;
    void * value;
    while(zhash_iterator_next(&itr, &id, &value)) {
        if (!zhash_contains(A, &id))
            zhash_put(A, &id, &value, NULL, NULL);
    }
}
Example #4
0
// Remove all elements from A which appear in B
static void removeAll(zhash_t * A, zhash_t  * B)
{
    zhash_iterator_t itr;
    zhash_iterator_init(A, &itr);
    uint64_t id = -1;
    void * value;
    while(zhash_iterator_next(&itr, &id, &value)) {
        if (zhash_contains(B, &id))
            zhash_iterator_remove(&itr);
    }
}
Example #5
0
static void print_manager(vx_resc_manager_t * mgr)
{

    printf(" #mgr has  %d worlds:\n", zhash_size(mgr->allLiveSets));

    zhash_iterator_t world_itr;
    zhash_iterator_init(mgr->allLiveSets, &world_itr);
    uint32_t worldId = 0;
    zhash_t * buffer_map = NULL;
    while (zhash_iterator_next(&world_itr, &worldId, &buffer_map)) {
        zhash_iterator_t buffer_itr;
        zhash_iterator_init(buffer_map, &buffer_itr);
        printf("  >world %d contains %d buffers:\n", worldId, zhash_size(buffer_map));

        char * buffer_name = NULL;
        zhash_t * res_map = NULL;
        while(zhash_iterator_next(&buffer_itr, &buffer_name, &res_map)) {
            zhash_iterator_t res_itr;
            zhash_iterator_init(res_map, &res_itr);
            printf("  >>buffer %s (%d): ", buffer_name, zhash_size(res_map));

            uint64_t vrid = 0;
            vx_resc_t * vr = NULL;
            while (zhash_iterator_next(&res_itr, &vrid, &vr)) {
                printf("%"PRIu64" ", vrid);
            }
            printf("\n");
        }
    }

    printf(" #aggregate (%d): ", zhash_size(mgr->remoteResc));
    zhash_iterator_t res_itr;
    zhash_iterator_init(mgr->remoteResc, &res_itr);
    uint64_t vrid = 0;
    vx_resc_t * vr = NULL;
    while (zhash_iterator_next(&res_itr, &vrid, &vr)) {
        printf("%"PRIu64" ", vrid);
    }
    printf("\n");
}
Example #6
0
static vx_code_output_stream_t * make_buffer_resource_codes(vx_buffer_t * buffer, zhash_t * resources)
{
    vx_code_output_stream_t * couts = vx_code_output_stream_create(256);
    couts->write_uint32(couts, OP_BUFFER_RESOURCES); // tell the display which resources are currently in use
    couts->write_uint32(couts, buffer->world->worldID);
    couts->write_str(couts, buffer->name);
    couts->write_uint32(couts, zhash_size(resources));

    zhash_iterator_t itr;
    zhash_iterator_init(resources, &itr);

    uint64_t guid = -1;
    vx_resc_t *resc = NULL;
    while (zhash_iterator_next(&itr, &guid, &resc))
        couts->write_uint64(couts, guid);
    return couts;
}
Example #7
0
int
eecs467_set_camera (vx_application_t *app, const float eye[3], const float lookat[3], const float up[3])
{
    int set = 0;
    eecs467_default_implementation_t *impl = app->impl;
    pthread_mutex_lock (&impl->mutex);
    {
        zhash_iterator_t zit;
        zhash_iterator_init (impl->layers, &zit);
        vx_layer_t *layer = NULL;
        while (zhash_iterator_next (&zit, NULL, &layer)) {
            vx_layer_camera_lookat (layer, eye, lookat, up, 1);
            set++;
        }
    }
    pthread_mutex_unlock (&impl->mutex);
    return set;
}
Example #8
0
// Pass in a codes describing which resources are no longer in use. Decrement user counts,
// and return a list of all resources whos counts have reached zero, which therefore
// should be deleted from the display using a OP_DEALLOC_RESOURCES opcode
void vx_resc_manager_buffer_resources(vx_resc_manager_t * mgr, const uint8_t * data, int datalen)
{
    if (0) print_manager(mgr);

    vx_code_input_stream_t * cins = vx_code_input_stream_create(data, datalen);
    int code = cins->read_uint32(cins);
    assert(code == OP_BUFFER_RESOURCES);
    int worldID = cins->read_uint32(cins);
    char * name = strdup(cins->read_str(cins)); //freed when cur_resources is eventually removed from the buffer map
    int count = cins->read_uint32(cins);

    zhash_t * cur_resources = zhash_create(sizeof(uint64_t), sizeof(vx_resc_t*), zhash_uint64_hash, zhash_uint64_equals);
    vx_resc_t * vr = NULL;
    for (int i = 0; i < count; i++) {
        uint64_t id = cins->read_uint64(cins);
        zhash_put(cur_resources, &id, &vr, NULL, NULL);
    }
    assert(cins->pos == cins->len); // we've emptied the stream
    vx_code_input_stream_destroy(cins);

    // 1 Update our records
    zhash_t * worldBuffers = NULL;
    zhash_get(mgr->allLiveSets, &worldID, &worldBuffers);
    if (worldBuffers == NULL) {
        worldBuffers = zhash_create(sizeof(char*), sizeof(zhash_t*), zhash_str_hash, zhash_str_equals);
        zhash_put(mgr->allLiveSets, &worldID, &worldBuffers, NULL, NULL);
    }

    zhash_t * old_resources = NULL;
    char * old_name = NULL;
    zhash_put(worldBuffers, &name, &cur_resources, &old_name, &old_resources);
    free(old_name);

    // 2 Figure out which resources have become unused:
    if(old_resources != NULL) {
        removeAll(old_resources, cur_resources);

        zarray_t * dealloc = zarray_create(sizeof(uint64_t));

        // now 'old_resources' contains only the resources that are no longer referenced
        // iterate through each one, and see if there is a buffer somewhere that references it
        zhash_iterator_t prev_itr;
        zhash_iterator_init(old_resources, &prev_itr);
        uint64_t id = -1;
        vx_resc_t * vr = NULL;
        while(zhash_iterator_next(&prev_itr, &id, &vr)) {
            // Check all worlds
            zhash_iterator_t  world_itr;// gives us all worlds
            zhash_iterator_init(mgr->allLiveSets, &world_itr);
            uint32_t wIDl = -1;
            zhash_t * buffer_map = NULL;
            while(zhash_iterator_next(&world_itr, &wIDl, &buffer_map)) {
                zhash_iterator_t buffer_itr; // gives us all buffers
                zhash_iterator_init(buffer_map, &buffer_itr);
                char * bName = NULL;
                zhash_t * resc_map = NULL;
                while(zhash_iterator_next(&buffer_itr, &bName, &resc_map)) {
                    if (zhash_contains(resc_map, &id)) {
                        goto continue_outer_loop;
                    }
                }

            }

            // If none of the worlds have this resource, we need to flag removal
            zarray_add(dealloc, &id);

          continue_outer_loop:
            ;
        }


        // 3 Issue dealloc commands
        if (zarray_size(dealloc) > 0) {
            vx_code_output_stream_t * couts = vx_code_output_stream_create(512);
            couts->write_uint32(couts, OP_DEALLOC_RESOURCES);
            couts->write_uint32(couts, zarray_size(dealloc));
            for (int i = 0; i < zarray_size(dealloc); i++) {
                uint64_t id = 0;
                zarray_get(dealloc, i, &id);
                couts->write_uint64(couts, id);
            }

            mgr->disp->send_codes(mgr->disp, couts->data, couts->pos);

            vx_code_output_stream_destroy(couts);

            // Also remove the resources we deallocated from remoteResc
            for (int i = 0; i < zarray_size(dealloc); i++) {
                uint64_t id = 0;
                zarray_get(dealloc, i, &id);

                assert(zhash_contains(mgr->remoteResc, &id));
                zhash_remove(mgr->remoteResc, &id, NULL, NULL);
            }

        }
        zarray_destroy(dealloc);
        zhash_destroy(old_resources);

    }
    if (0) {
        print_manager(mgr);
        printf("\n\n");
    }
}
Example #9
0
// this loop tries to run at X fps, and issue render commands
static void * render_loop(void * foo)
{
    state_t * state = foo;
    if (verbose)printf("Starting render thread!\n");

    uint64_t render_count = 0;
    uint64_t last_mtime = vx_mtime();
    double avgDT = 1.0f/state->target_frame_rate;
    uint64_t avg_loop_us = 3000; // initial render time guess
    while (state->rendering) {
        int64_t sleeptime = (1000000 / state->target_frame_rate) - (int64_t) avg_loop_us;
        if (sleeptime > 0)
            usleep(sleeptime); // XXX fix to include render time

        // Diagnostic tracking
        uint64_t mtime_start = vx_mtime(); // XXX
        avgDT = avgDT*.9 + .1 * (mtime_start - last_mtime)/1000;
        last_mtime = mtime_start;
        render_count++;

        if (verbose) {
            if (render_count % 100 == 0)
                printf("Average render DT = %.3f FPS = %.3f avgloopus %"PRIu64" sleeptime = %"PRIi64"\n",
                       avgDT, 1.0/avgDT, avg_loop_us, sleeptime);
        }

        // prep the render data
        render_buffer_t rbuf;
        rbuf.state = state;
        rbuf.width = gtku_image_pane_get_width(state->imagePane);
        rbuf.height = gtku_image_pane_get_height(state->imagePane);
        if (rbuf.width == 0 && rbuf.height == 0)
            continue; // if the viewport is 0,0

        // smartly reuse, or reallocate the output pixel buffer when resizing occurs
        GdkPixbuf * pixbuf = state->pixbufs[state->cur_pb_idx];
        if (pixbuf == NULL || gdk_pixbuf_get_width(pixbuf) != rbuf.width || gdk_pixbuf_get_height(pixbuf) != rbuf.height) {
            if (pixbuf != NULL) {
                g_object_unref(pixbuf);
                free(state->pixdatas[state->cur_pb_idx]);
            }

            state->pixdatas[state->cur_pb_idx] = malloc(rbuf.width*rbuf.height*3); // can't stack allocate, can be too big (retina)
            pixbuf = gdk_pixbuf_new_from_data(state->pixdatas[state->cur_pb_idx], GDK_COLORSPACE_RGB, FALSE, 8,
                                              rbuf.width, rbuf.height, rbuf.width*3, NULL, NULL); // no destructor fn for pix data, handle manually
            state->pixbufs[state->cur_pb_idx] = pixbuf;
        }

        // second half of init:
        rbuf.out_buf = gdk_pixbuf_get_pixels(pixbuf);
        rbuf.format = GL_RGB;
        rbuf.rendered = 0;

        // 1 compute all the viewports
        render_info_t * rinfo = render_info_create();
        rinfo->viewport[0] = rinfo->viewport[1] = 0;
        rinfo->viewport[2] = rbuf.width;
        rinfo->viewport[3] = rbuf.height;

        {
            zhash_iterator_t itr;
            uint32_t layer_id = 0;
            layer_info_t * linfo = NULL;
            zhash_iterator_init(state->layer_info_map, &itr);
            while(zhash_iterator_next(&itr, &layer_id, &linfo)){
                zarray_add(rinfo->layers, &linfo);
            }
            zarray_sort(rinfo->layers, zvx_layer_info_compare);
        }

        zarray_t * fp = zarray_create(sizeof(matd_t*));

        matd_t *mm = matd_create(4,4); zarray_add(fp, &mm);
        matd_t *pm = matd_create(4,4); zarray_add(fp, &pm);

        pthread_mutex_lock(&state->mutex);
        for (int i = 0; i < zarray_size(rinfo->layers); i++) {
            layer_info_t *linfo = NULL;
            zarray_get(rinfo->layers, i, &linfo);

            int * viewport = vx_viewport_mgr_get_pos(linfo->vp_mgr, rinfo->viewport, mtime_start);
            vx_camera_pos_t *pos = default_cam_mgr_get_cam_pos(linfo->cam_mgr, viewport, mtime_start);

            // store viewport, pos
            zhash_put(rinfo->layer_positions, &linfo->layer_id, &viewport, NULL, NULL);
            zhash_put(rinfo->camera_positions, &linfo->layer_id, &pos, NULL, NULL);

            // feed the actual camera/projection matrix to the gl side
            vx_camera_pos_model_matrix(pos,mm->data);
            vx_camera_pos_projection_matrix(pos, pm->data);

            matd_t * pmmm = matd_multiply(pm,mm); zarray_add(fp, &pmmm);

            float pm16[16];
            vx_util_copy_floats(pmmm->data, pm16, 16);

            float eye3[16];
            vx_util_copy_floats(pos->eye, eye3, 3);

            vx_gl_renderer_set_layer_render_details(state->glrend, linfo->layer_id, viewport, pm16, eye3);
        }

        // 2 Render the data
        task_thread_schedule_blocking(gl_thread, render_task, &rbuf);

        render_info_t * old = state->last_render_info;
        state->last_render_info = rinfo;

        pthread_mutex_unlock(&state->mutex);


        // 3 if a render occurred, then swap gtk buffers
        if (rbuf.rendered) {

            // point to the correct buffer for the next render:
            state->cur_pb_idx = (state->cur_pb_idx +1 ) % 2;

            // flip y coordinate in place:
            vx_util_flipy(rbuf.width*3, rbuf.height, rbuf.out_buf);

            // swap the image's backing buffer
            g_object_ref(pixbuf); // XXX Since gtku always unrefs with each of these calls, increment accordingly
            gtku_image_pane_set_buffer(state->imagePane, pixbuf);
        }

        // 3.1 If a movie is in progress, also need to serialize the frame
        pthread_mutex_lock(&state->movie_mutex);
        if (state->movie_file != NULL) {

            int last_idx = (state->cur_pb_idx + 1) % 2;
            GdkPixbuf * pb = state->pixbufs[last_idx];

            movie_frame_t * movie_img = calloc(1, sizeof(movie_frame_t));
            movie_img->mtime = mtime_start;
            movie_img->width = gdk_pixbuf_get_width(pb);
            movie_img->height = gdk_pixbuf_get_height(pb);
            movie_img->stride = 3*movie_img->width;
            movie_img->buf = malloc(movie_img->stride*movie_img->height);
            memcpy(movie_img->buf, state->pixdatas[last_idx], movie_img->stride*movie_img->height);


            // Alloc in this thread, dealloc in movie thread
            zarray_add(state->movie_pending, & movie_img);

            pthread_cond_signal(&state->movie_cond);

        }
        pthread_mutex_unlock(&state->movie_mutex);


        // cleanup
        if (old)
            render_info_destroy(old);
        zarray_vmap(fp, matd_destroy);
        zarray_destroy(fp);


        uint64_t mtime_end = vx_mtime();
        avg_loop_us = (uint64_t)(.5*avg_loop_us + .5 * 1000 * (mtime_end - mtime_start));
    }
    if (verbose) printf("Render thread exiting\n");

    pthread_exit(NULL);

}
Example #10
0
void * camera_loop(void * data)
{
    state_t * state = data;

    sleep(2); // wait for 2 seconds before starting the animation

    matd_t * zaxis = matd_create(3,1);
    zaxis->data[2] = 1;

    vx_buffer_add_back(vx_world_get_buffer(state->world, "cam-circle"), vxo_chain(vxo_mat_scale(CAM_RADIUS),
                       vxo_circle(vxo_lines_style(vx_green, 3))));
    vx_buffer_swap(vx_world_get_buffer(state->world, "cam-circle"));


    int64_t start_mtime =  vx_util_mtime();
    // tell each layer to follow
    pthread_mutex_lock(&state->mutex);
    {
        zhash_iterator_t itr;
        zhash_iterator_init(state->layers, &itr);
        vx_display_t * key;
        vx_layer_t * vl;

        while(zhash_iterator_next(&itr, &key, &vl)) {
            if (1) {
                float eye3[] = {CAM_RADIUS,-CAM_RADIUS,45.0f};
                float lookat3[] = {CAM_RADIUS,0,0.0f};
                float up3[] = {0,1,0};
                vx_layer_camera_lookat(vl, eye3, lookat3, up3, 0);
            }
        }
    }
    pthread_mutex_unlock(&state->mutex);

    while (state->running) {
        // 5 seconds revolutions
        double rad = ( (vx_util_mtime() - start_mtime) % 5000) * 2* M_PI / 5e3;

        // compute the current position and orientation of the "robot"
        matd_t * orientation = matd_angle_axis_to_quat(rad, zaxis);
        matd_t * pos =  matd_create(3,1);
        pos->data[0] = cos(rad) * CAM_RADIUS;
        pos->data[1] = sin(rad) * CAM_RADIUS;

        // tell each layer to follow
        pthread_mutex_lock(&state->mutex);
        {
            zhash_iterator_t itr;
            zhash_iterator_init(state->layers, &itr);
            vx_display_t * key;
            vx_layer_t * vl;

            while(zhash_iterator_next(&itr, &key, &vl)) {
                vx_layer_camera_follow(vl, pos->data, orientation->data, 1);
            }
        }
        pthread_mutex_unlock(&state->mutex);


        vx_buffer_add_back(vx_world_get_buffer(state->world, "robot-proxy"),
                           vxo_chain(vxo_mat_quat_pos(orientation->data, pos->data),
                                     vxo_box(vxo_lines_style(vx_purple, 3))));
        vx_buffer_swap(vx_world_get_buffer(state->world, "robot-proxy"));


        matd_destroy(orientation);
        matd_destroy(pos);

        usleep(100000);
    }

    matd_destroy(zaxis);

    return NULL;
}
Example #11
0
static void * run_process(void * data)
{
    vx_world_t * world = data;


    while (world->process_running) {
        vx_world_listener_t * listener = NULL;
        char * buffer_name = NULL;

        // 1) Wait until there's data
        pthread_mutex_lock(&world->queue_mutex);
        while (zarray_size(world->buffer_queue) == 0 && zarray_size(world->listener_queue) == 0 && world->process_running) {
            pthread_cond_wait(&world->queue_cond, &world->queue_mutex);
        }

        if (!world->process_running) { // XXX cleaning out the queue?
            pthread_mutex_unlock(&world->queue_mutex);
            break;
        }

        // Processing new listeners takes priority
        if ( zarray_size(world->listener_queue) > 0) {
            zarray_get(world->listener_queue, 0, &listener);
            zarray_remove_index(world->listener_queue, 0, 0);
        } else {
            assert(zarray_size(world->buffer_queue) > 0);
            zarray_get(world->buffer_queue, 0, &buffer_name);
            zarray_remove_index(world->buffer_queue, 0, 0);
        }
        pthread_mutex_unlock(&world->queue_mutex);

        // Operation A: New listener
        if (listener != NULL) {
            // re-transmit each buffer that has already been serialized
            pthread_mutex_lock(&world->buffer_mutex);
            zhash_iterator_t itr;
            zhash_iterator_init(world->buffer_map, &itr);
            char * name = NULL;
            vx_buffer_t * buffer = NULL;
            while(zhash_iterator_next(&itr, &name, &buffer)) {
                if (buffer->front_codes->pos != 0) {
                    vx_code_output_stream_t * bresc_codes = make_buffer_resource_codes(buffer, buffer->front_resc);

                    // Doing a swap in 3 steps (instead of 4) like this
                    // is only safe if the listener is brand new, which we are
                    // guaranteed is the case in this chunk of code
                    listener->send_codes(listener, bresc_codes->data, bresc_codes->pos);
                    listener->send_resources(listener, buffer->front_resc);
                    listener->send_codes(listener, buffer->front_codes->data, buffer->front_codes->pos);

                    vx_code_output_stream_destroy(bresc_codes);
                }
            }

            pthread_mutex_unlock(&world->buffer_mutex);
        }

        // Operation B: buffer swap
        if (buffer_name != NULL) {
            vx_buffer_t * buffer = NULL;
            pthread_mutex_lock(&world->buffer_mutex);
            zhash_get(world->buffer_map, &buffer_name, &buffer);
            pthread_mutex_unlock(&world->buffer_mutex);

            delayed_swap(buffer);
        }

    }

    pthread_exit(NULL);
}