예제 #1
0
int
main(int argc, char **argv)
{
    Data data;
    cg_onscreen_t *onscreen;
    cg_error_t *error = NULL;
    cg_vertex_p2c4_t triangle_vertices[] = {
        { 0, 0.7, 0xff, 0x00, 0x00, 0xff },
        { -0.7, -0.7, 0x00, 0xff, 0x00, 0xff },
        { 0.7, -0.7, 0x00, 0x00, 0xff, 0xff }
    };
    cg_renderer_t *renderer;
    cg_display_t *display;
    uv_loop_t *loop = uv_default_loop();

    renderer = cg_renderer_new();
    cg_renderer_add_constraint(renderer,
                               CG_RENDERER_CONSTRAINT_SUPPORTS_CG_GLES2);

    if (!cg_renderer_connect(renderer, &error)) {
        c_error("%s", error->message);
        exit(1);
    }

    display = cg_display_new(renderer, NULL);
    data.dev = cg_device_new();
    cg_device_set_display(data.dev, display);

    if (!cg_device_connect(data.dev, &error)) {
        c_error("%s", error->message);
        exit(1);
    }

    onscreen = cg_onscreen_new(data.dev, 640, 480);
    cg_onscreen_show(onscreen);
    data.fb = onscreen;

    /* Prepare onscreen primitive */
    data.triangle = cg_primitive_new_p2c4(
        data.dev, CG_VERTICES_MODE_TRIANGLES, 3, triangle_vertices);
    data.pipeline = cg_pipeline_new(data.dev);

    data.offscreen_texture = cg_texture_2d_new_with_size(
        data.dev, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT);
    data.offscreen = cg_offscreen_new_with_texture(data.offscreen_texture);

    data.gles2_ctx = cg_gles2_context_new(data.dev, &error);
    if (!data.gles2_ctx) {
        c_error("Failed to create GLES2 context: %s\n", error->message);
    }

    data.gles2_vtable = cg_gles2_context_get_vtable(data.gles2_ctx);

    /* Draw scene with GLES2 */
    if (!cg_push_gles2_context(
            data.dev, data.gles2_ctx, data.fb, data.fb, &error)) {
        c_error("Failed to push gles2 context: %s\n", error->message);
    }

    cg_pop_gles2_context(data.dev);

    cg_onscreen_add_frame_callback(
        CG_ONSCREEN(data.fb), frame_event_cb, &data, NULL); /* destroy notify */

    uv_idle_init(loop, &data.idle);
    data.idle.data = &data;
    uv_idle_start(&data.idle, paint_cb);

    cg_uv_set_mainloop(data.dev, loop);
    uv_run(loop, UV_RUN_DEFAULT);

    return 0;
}
예제 #2
0
bool
cg_device_connect(cg_device_t *dev, cg_error_t **error)
{
    uint8_t white_pixel[] = { 0xff, 0xff, 0xff, 0xff };
    const cg_winsys_vtable_t *winsys;
    int i;
    cg_error_t *internal_error = NULL;

    if (dev->connected)
        return true;

    /* Mark as connected now to avoid recursion issues,
     * but revert in error paths */
    dev->connected = true;

    if (!dev->renderer) {
        cg_renderer_t *renderer = cg_renderer_new();
        if (!cg_renderer_connect(renderer, error)) {
            cg_object_unref(renderer);
            dev->connected = false;
            return false;
        }
        cg_device_set_renderer(dev, renderer);
    }

    if (!dev->display) {
        cg_display_t *display = cg_display_new(dev->renderer, NULL);
        if (!cg_display_setup(display, error)) {
            cg_object_unref(display);
            dev->connected = false;
            return false;
        }
        cg_device_set_display(dev, display);
    }

    /* This is duplicated data, but it's much more convenient to have
       the driver attached to the context and the value is accessed a
       lot throughout CGlib */
    dev->driver = dev->renderer->driver;

    /* Again this is duplicated data, but it convenient to be able
     * access these from the context. */
    dev->driver_vtable = dev->renderer->driver_vtable;
    dev->texture_driver = dev->renderer->texture_driver;

    for (i = 0; i < C_N_ELEMENTS(dev->private_features); i++)
        dev->private_features[i] |= dev->renderer->private_features[i];

    winsys = _cg_device_get_winsys(dev);
    if (!winsys->device_init(dev, error)) {
        dev->connected = false;
        return false;
    }

    dev->attribute_name_states_hash =
        c_hash_table_new_full(c_str_hash, c_str_equal, c_free, c_free);
    dev->attribute_name_index_map = NULL;
    dev->n_attribute_names = 0;

    /* The "cg_color_in" attribute needs a deterministic name_index
     * so we make sure it's the first attribute name we register */
    _cg_attribute_register_attribute_name(dev, "cg_color_in");

    dev->uniform_names =
        c_ptr_array_new_with_free_func((c_destroy_func_t)c_free);
    dev->uniform_name_hash = c_hash_table_new(c_str_hash, c_str_equal);
    dev->n_uniform_names = 0;

    /* Initialise the driver specific state */
    _cg_init_feature_overrides(dev);

    /* XXX: ONGOING BUG: Intel viewport scissor
     *
     * Intel gen6 drivers don't currently correctly handle offset
     * viewports, since primitives aren't clipped within the bounds of
     * the viewport.  To workaround this we push our own clip for the
     * viewport that will use scissoring to ensure we clip as expected.
     *
     * TODO: file a bug upstream!
     */
    if (dev->gpu.driver_package == CG_GPU_INFO_DRIVER_PACKAGE_MESA &&
        dev->gpu.architecture == CG_GPU_INFO_ARCHITECTURE_SANDYBRIDGE &&
        !getenv("CG_DISABLE_INTEL_VIEWPORT_SCISSORT_WORKAROUND"))
        dev->needs_viewport_scissor_workaround = true;
    else
        dev->needs_viewport_scissor_workaround = false;

    dev->sampler_cache = _cg_sampler_cache_new(dev);

    _cg_pipeline_init_default_pipeline();
    _cg_pipeline_init_default_layers();
    _cg_pipeline_init_state_hash_functions();
    _cg_pipeline_init_layer_state_hash_functions();

    dev->current_clip_stack_valid = false;
    dev->current_clip_stack = NULL;

    c_matrix_init_identity(&dev->identity_matrix);
    c_matrix_init_identity(&dev->y_flip_matrix);
    c_matrix_scale(&dev->y_flip_matrix, 1, -1, 1);

    dev->texture_units =
        c_array_new(false, false, sizeof(cg_texture_unit_t));

    if (_cg_has_private_feature(dev, CG_PRIVATE_FEATURE_ANY_GL)) {
        /* See cg-pipeline.c for more details about why we leave texture unit
         * 1
         * active by default... */
        dev->active_texture_unit = 1;
        GE(dev, glActiveTexture(GL_TEXTURE1));
    }

    dev->opaque_color_pipeline = cg_pipeline_new(dev);
    dev->codegen_header_buffer = c_string_new("");
    dev->codegen_source_buffer = c_string_new("");

    dev->default_gl_texture_2d_tex = NULL;
    dev->default_gl_texture_3d_tex = NULL;

    dev->framebuffers = NULL;
    dev->current_draw_buffer = NULL;
    dev->current_read_buffer = NULL;
    dev->current_draw_buffer_state_flushed = 0;
    dev->current_draw_buffer_changes = CG_FRAMEBUFFER_STATE_ALL;

    c_list_init(&dev->onscreen_events_queue);
    c_list_init(&dev->onscreen_dirty_queue);

    c_queue_init(&dev->gles2_context_stack);

    dev->current_pipeline = NULL;
    dev->current_pipeline_changes_since_flush = 0;
    dev->current_pipeline_with_color_attrib = false;

    _cg_bitmask_init(&dev->enabled_custom_attributes);
    _cg_bitmask_init(&dev->enable_custom_attributes_tmp);
    _cg_bitmask_init(&dev->changed_bits_tmp);

    dev->max_texture_units = -1;
    dev->max_activateable_texture_units = -1;

    dev->current_gl_program = 0;

    dev->current_gl_dither_enabled = true;
    dev->current_gl_color_mask = CG_COLOR_MASK_ALL;

    dev->gl_blend_enable_cache = false;

    dev->depth_test_enabled_cache = false;
    dev->depth_test_function_cache = CG_DEPTH_TEST_FUNCTION_LESS;
    dev->depth_writing_enabled_cache = true;
    dev->depth_range_near_cache = 0;
    dev->depth_range_far_cache = 1;

    dev->pipeline_cache = _cg_pipeline_cache_new();

    for (i = 0; i < CG_BUFFER_BIND_TARGET_COUNT; i++)
        dev->current_buffer[i] = NULL;

    dev->stencil_pipeline = cg_pipeline_new(dev);

    dev->rectangle_byte_indices = NULL;
    dev->rectangle_short_indices = NULL;
    dev->rectangle_short_indices_len = 0;

    dev->texture_download_pipeline = NULL;
    dev->blit_texture_pipeline = NULL;

#if defined(CG_HAS_GL_SUPPORT)
    if ((dev->driver == CG_DRIVER_GL3)) {
        GLuint vertex_array;

        /* In a forward compatible context, GL 3 doesn't support rendering
         * using the default vertex array object. CGlib doesn't use vertex
         * array objects yet so for now we just create a dummy array
         * object that we will use as our own default object. Eventually
         * it could be good to attach the vertex array objects to
         * cg_primitive_ts */
        dev->glGenVertexArrays(1, &vertex_array);
        dev->glBindVertexArray(vertex_array);
    }
#endif

    dev->current_modelview_entry = NULL;
    dev->current_projection_entry = NULL;
    _cg_matrix_entry_identity_init(&dev->identity_entry);
    _cg_matrix_entry_cache_init(&dev->builtin_flushed_projection);
    _cg_matrix_entry_cache_init(&dev->builtin_flushed_modelview);

    /* Create default textures used for fall backs */
    dev->default_gl_texture_2d_tex =
        cg_texture_2d_new_from_data(dev,
                                    1,
                                    1,
                                    CG_PIXEL_FORMAT_RGBA_8888_PRE,
                                    0, /* rowstride */
                                    white_pixel,
                                    NULL); /* abort on error */

    /* If 3D or rectangle textures aren't supported then these will
     * return errors that we can simply ignore. */
    internal_error = NULL;
    dev->default_gl_texture_3d_tex =
        cg_texture_3d_new_from_data(dev,
                                    1,
                                    1,
                                    1, /* width, height, depth */
                                    CG_PIXEL_FORMAT_RGBA_8888_PRE,
                                    0, /* rowstride */
                                    0, /* image stride */
                                    white_pixel,
                                    &internal_error);
    if (internal_error)
        cg_error_free(internal_error);

    dev->buffer_map_fallback_array = c_byte_array_new();
    dev->buffer_map_fallback_in_use = false;

    c_list_init(&dev->fences);

    dev->atlas_set = cg_atlas_set_new(dev);
    cg_atlas_set_set_components(dev->atlas_set, CG_TEXTURE_COMPONENTS_RGBA);
    cg_atlas_set_set_premultiplied(dev->atlas_set, false);
    cg_atlas_set_add_atlas_callback(dev->atlas_set,
                                    _cg_atlas_texture_atlas_event_handler,
                                    NULL, /* user data */
                                    NULL); /* destroy */

    return true;
}